blob: bdebc76a9b1f7cfa8c3ac59ec232a7bb03144a0a [file] [log] [blame]
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00001//===-- ARMAsmParser.cpp - Parse ARM assembly to MCInst instructions ------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Evan Cheng94b95502011-07-26 00:24:13 +000010#include "MCTargetDesc/ARMBaseInfo.h"
Evan Chengee04a6d2011-07-20 23:34:39 +000011#include "MCTargetDesc/ARMAddressingModes.h"
12#include "MCTargetDesc/ARMMCExpr.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000013#include "llvm/MC/MCParser/MCAsmLexer.h"
14#include "llvm/MC/MCParser/MCAsmParser.h"
15#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Rafael Espindola64695402011-05-16 16:17:21 +000016#include "llvm/MC/MCAsmInfo.h"
Jim Grosbach642fc9c2010-11-05 22:33:53 +000017#include "llvm/MC/MCContext.h"
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000018#include "llvm/MC/MCStreamer.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Evan Cheng78011362011-08-23 20:15:21 +000021#include "llvm/MC/MCInstrDesc.h"
Evan Cheng94b95502011-07-26 00:24:13 +000022#include "llvm/MC/MCRegisterInfo.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000023#include "llvm/MC/MCSubtargetInfo.h"
Evan Cheng94b95502011-07-26 00:24:13 +000024#include "llvm/MC/MCTargetAsmParser.h"
Jim Grosbach89df9962011-08-26 21:43:41 +000025#include "llvm/Support/MathExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000026#include "llvm/Support/SourceMgr.h"
Evan Cheng3e74d6f2011-08-24 18:08:43 +000027#include "llvm/Support/TargetRegistry.h"
Daniel Dunbarfa315de2010-08-11 06:37:12 +000028#include "llvm/Support/raw_ostream.h"
Jim Grosbach11e03e72011-08-22 18:50:36 +000029#include "llvm/ADT/BitVector.h"
Benjamin Kramer75ca4b92011-07-08 21:06:23 +000030#include "llvm/ADT/OwningPtr.h"
Evan Cheng94b95502011-07-26 00:24:13 +000031#include "llvm/ADT/STLExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000032#include "llvm/ADT/SmallVector.h"
Owen Anderson0c9f2502011-01-13 22:50:36 +000033#include "llvm/ADT/StringExtras.h"
Daniel Dunbar345a9a62010-08-11 06:37:20 +000034#include "llvm/ADT/StringSwitch.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000035#include "llvm/ADT/Twine.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000036
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000037using namespace llvm;
38
Chris Lattner3a697562010-10-28 17:20:03 +000039namespace {
Bill Wendling146018f2010-11-06 21:42:12 +000040
41class ARMOperand;
Jim Grosbach16c74252010-10-29 14:46:02 +000042
Evan Cheng94b95502011-07-26 00:24:13 +000043class ARMAsmParser : public MCTargetAsmParser {
Evan Chengffc0e732011-07-09 05:47:46 +000044 MCSubtargetInfo &STI;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000045 MCAsmParser &Parser;
46
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000047 struct {
48 ARMCC::CondCodes Cond; // Condition for IT block.
49 unsigned Mask:4; // Condition mask for instructions.
50 // Starting at first 1 (from lsb).
51 // '1' condition as indicated in IT.
52 // '0' inverse of condition (else).
53 // Count of instructions in IT block is
54 // 4 - trailingzeroes(mask)
55
56 bool FirstCond; // Explicit flag for when we're parsing the
57 // First instruction in the IT block. It's
58 // implied in the mask, so needs special
59 // handling.
60
61 unsigned CurPosition; // Current position in parsing of IT
62 // block. In range [0,3]. Initialized
63 // according to count of instructions in block.
64 // ~0U if no active IT block.
65 } ITState;
66 bool inITBlock() { return ITState.CurPosition != ~0U;}
Jim Grosbacha1109882011-09-02 23:22:08 +000067 void forwardITPosition() {
68 if (!inITBlock()) return;
69 // Move to the next instruction in the IT block, if there is one. If not,
70 // mark the block as done.
71 unsigned TZ = CountTrailingZeros_32(ITState.Mask);
72 if (++ITState.CurPosition == 5 - TZ)
73 ITState.CurPosition = ~0U; // Done with the IT block after this.
74 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000075
76
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000077 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000078 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
79
80 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000081 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
82
Jim Grosbach1355cf12011-07-26 17:10:22 +000083 int tryParseRegister();
84 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d87ec22011-07-26 20:41:24 +000085 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000086 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +000087 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000088 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
89 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbach7ce05792011-08-03 23:50:40 +000090 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
91 unsigned &ShiftAmount);
Jim Grosbach1355cf12011-07-26 17:10:22 +000092 bool parseDirectiveWord(unsigned Size, SMLoc L);
93 bool parseDirectiveThumb(SMLoc L);
94 bool parseDirectiveThumbFunc(SMLoc L);
95 bool parseDirectiveCode(SMLoc L);
96 bool parseDirectiveSyntax(SMLoc L);
Kevin Enderby515d5092009-10-15 20:48:48 +000097
Jim Grosbach1355cf12011-07-26 17:10:22 +000098 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach89df9962011-08-26 21:43:41 +000099 bool &CarrySetting, unsigned &ProcessorIMod,
100 StringRef &ITMask);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000101 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +0000102 bool &CanAcceptPredicationCode);
Jim Grosbach16c74252010-10-29 14:46:02 +0000103
Evan Chengebdeeab2011-07-08 01:53:10 +0000104 bool isThumb() const {
105 // FIXME: Can tablegen auto-generate this?
Evan Chengffc0e732011-07-09 05:47:46 +0000106 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000107 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000108 bool isThumbOne() const {
Evan Chengffc0e732011-07-09 05:47:46 +0000109 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000110 }
Jim Grosbach47a0d522011-08-16 20:45:50 +0000111 bool isThumbTwo() const {
112 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
113 }
Jim Grosbach194bd892011-08-16 22:20:01 +0000114 bool hasV6Ops() const {
115 return STI.getFeatureBits() & ARM::HasV6Ops;
116 }
James Molloyacad68d2011-09-28 14:21:38 +0000117 bool hasV7Ops() const {
118 return STI.getFeatureBits() & ARM::HasV7Ops;
119 }
Evan Cheng32869202011-07-08 22:36:29 +0000120 void SwitchMode() {
Evan Chengffc0e732011-07-09 05:47:46 +0000121 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
122 setAvailableFeatures(FB);
Evan Cheng32869202011-07-08 22:36:29 +0000123 }
James Molloyacad68d2011-09-28 14:21:38 +0000124 bool isMClass() const {
125 return STI.getFeatureBits() & ARM::FeatureMClass;
126 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000127
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000128 /// @name Auto-generated Match Functions
129 /// {
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000130
Chris Lattner0692ee62010-09-06 19:11:01 +0000131#define GET_ASSEMBLER_HEADER
132#include "ARMGenAsmMatcher.inc"
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000133
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000134 /// }
135
Jim Grosbach89df9962011-08-26 21:43:41 +0000136 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000137 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000138 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000139 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000140 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000141 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000142 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000143 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000144 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000145 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000146 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachf6c05252011-07-21 17:23:04 +0000147 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
148 StringRef Op, int Low, int High);
149 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
150 return parsePKHImm(O, "lsl", 0, 31);
151 }
152 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
153 return parsePKHImm(O, "asr", 1, 32);
154 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000155 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach580f4a92011-07-25 22:20:28 +0000156 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000157 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000158 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000159 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach251bf252011-08-10 21:56:18 +0000160 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9d390362011-10-03 23:38:36 +0000161 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000162
163 // Asm Match Converter Methods
Jim Grosbacha77295d2011-09-08 22:07:06 +0000164 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
165 const SmallVectorImpl<MCParsedAsmOperand*> &);
166 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
167 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheeec0252011-09-08 00:39:19 +0000168 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
169 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachee2c2a42011-09-16 21:55:56 +0000170 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
171 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000172 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000173 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson9ab0f252011-08-26 20:43:14 +0000174 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
175 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach548340c2011-08-11 19:22:40 +0000176 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
177 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000178 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000179 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7b8f46c2011-08-11 21:17:22 +0000180 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
181 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000182 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
183 const SmallVectorImpl<MCParsedAsmOperand*> &);
184 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
185 const SmallVectorImpl<MCParsedAsmOperand*> &);
186 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
187 const SmallVectorImpl<MCParsedAsmOperand*> &);
188 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
189 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000190 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
191 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach14605d12011-08-11 20:28:23 +0000192 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
193 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach623a4542011-08-10 22:42:16 +0000194 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
195 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach88ae2bc2011-08-19 22:07:46 +0000196 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
197 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach189610f2011-07-26 18:25:39 +0000198
199 bool validateInstruction(MCInst &Inst,
200 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachf8fce712011-08-11 17:35:48 +0000201 void processInstruction(MCInst &Inst,
202 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachd54b4e62011-08-16 21:12:37 +0000203 bool shouldOmitCCOutOperand(StringRef Mnemonic,
204 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach189610f2011-07-26 18:25:39 +0000205
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000206public:
Jim Grosbach47a0d522011-08-16 20:45:50 +0000207 enum ARMMatchResultTy {
Jim Grosbach194bd892011-08-16 22:20:01 +0000208 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000209 Match_RequiresNotITBlock,
Jim Grosbach194bd892011-08-16 22:20:01 +0000210 Match_RequiresV6,
211 Match_RequiresThumb2
Jim Grosbach47a0d522011-08-16 20:45:50 +0000212 };
213
Evan Chengffc0e732011-07-09 05:47:46 +0000214 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng94b95502011-07-26 00:24:13 +0000215 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Chengebdeeab2011-07-08 01:53:10 +0000216 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng32869202011-07-08 22:36:29 +0000217
Evan Chengebdeeab2011-07-08 01:53:10 +0000218 // Initialize the set of available features.
Evan Chengffc0e732011-07-09 05:47:46 +0000219 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000220
221 // Not in an ITBlock to start with.
222 ITState.CurPosition = ~0U;
Evan Chengebdeeab2011-07-08 01:53:10 +0000223 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000224
Jim Grosbach1355cf12011-07-26 17:10:22 +0000225 // Implementation of the MCTargetAsmParser interface:
226 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
227 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbach189610f2011-07-26 18:25:39 +0000228 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000229 bool ParseDirective(AsmToken DirectiveID);
230
Jim Grosbach47a0d522011-08-16 20:45:50 +0000231 unsigned checkTargetMatchPredicate(MCInst &Inst);
232
Jim Grosbach1355cf12011-07-26 17:10:22 +0000233 bool MatchAndEmitInstruction(SMLoc IDLoc,
234 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
235 MCStreamer &Out);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000236};
Jim Grosbach16c74252010-10-29 14:46:02 +0000237} // end anonymous namespace
238
Chris Lattner3a697562010-10-28 17:20:03 +0000239namespace {
240
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000241/// ARMOperand - Instances of this class represent a parsed ARM machine
242/// instruction.
Bill Wendling146018f2010-11-06 21:42:12 +0000243class ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000244 enum KindTy {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000245 k_CondCode,
246 k_CCOut,
247 k_ITCondMask,
248 k_CoprocNum,
249 k_CoprocReg,
250 k_Immediate,
251 k_FPImmediate,
252 k_MemBarrierOpt,
253 k_Memory,
254 k_PostIndexRegister,
255 k_MSRMask,
256 k_ProcIFlags,
Jim Grosbach460a9052011-10-07 23:56:00 +0000257 k_VectorIndex,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000258 k_Register,
259 k_RegisterList,
260 k_DPRRegisterList,
261 k_SPRRegisterList,
262 k_ShiftedRegister,
263 k_ShiftedImmediate,
264 k_ShifterImmediate,
265 k_RotateImmediate,
266 k_BitfieldDescriptor,
267 k_Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000268 } Kind;
269
Sean Callanan76264762010-04-02 22:27:05 +0000270 SMLoc StartLoc, EndLoc;
Bill Wendling24d22d22010-11-18 21:50:54 +0000271 SmallVector<unsigned, 8> Registers;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000272
273 union {
274 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000275 ARMCC::CondCodes Val;
276 } CC;
277
278 struct {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000279 unsigned Val;
280 } Cop;
281
282 struct {
Jim Grosbach89df9962011-08-26 21:43:41 +0000283 unsigned Mask:4;
284 } ITMask;
285
286 struct {
287 ARM_MB::MemBOpt Val;
288 } MBOpt;
289
290 struct {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000291 ARM_PROC::IFlags Val;
292 } IFlags;
293
294 struct {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000295 unsigned Val;
296 } MMask;
297
298 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000299 const char *Data;
300 unsigned Length;
301 } Tok;
302
303 struct {
304 unsigned RegNum;
305 } Reg;
306
Bill Wendling8155e5b2010-11-06 22:19:43 +0000307 struct {
Jim Grosbach460a9052011-10-07 23:56:00 +0000308 unsigned Val;
309 } VectorIndex;
310
311 struct {
Kevin Enderbycfe07242009-10-13 22:19:02 +0000312 const MCExpr *Val;
313 } Imm;
Jim Grosbach16c74252010-10-29 14:46:02 +0000314
Jim Grosbach9d390362011-10-03 23:38:36 +0000315 struct {
316 unsigned Val; // encoded 8-bit representation
317 } FPImm;
318
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +0000319 /// Combined record for all forms of ARM address expressions.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000320 struct {
321 unsigned BaseRegNum;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000322 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
323 // was specified.
324 const MCConstantExpr *OffsetImm; // Offset immediate value
325 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
326 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbach57dcb852011-10-11 17:29:55 +0000327 unsigned ShiftImm; // shift for OffsetReg.
328 unsigned Alignment; // 0 = no alignment specified
329 // n = alignment in bytes (8, 16, or 32)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000330 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbache53c87b2011-10-11 15:59:20 +0000331 } Memory;
Owen Anderson00828302011-03-18 22:50:18 +0000332
333 struct {
Jim Grosbach7ce05792011-08-03 23:50:40 +0000334 unsigned RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000335 bool isAdd;
336 ARM_AM::ShiftOpc ShiftTy;
337 unsigned ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000338 } PostIdxReg;
339
340 struct {
Jim Grosbach580f4a92011-07-25 22:20:28 +0000341 bool isASR;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000342 unsigned Imm;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000343 } ShifterImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000344 struct {
345 ARM_AM::ShiftOpc ShiftTy;
346 unsigned SrcReg;
347 unsigned ShiftReg;
348 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000349 } RegShiftedReg;
Owen Anderson92a20222011-07-21 18:54:16 +0000350 struct {
351 ARM_AM::ShiftOpc ShiftTy;
352 unsigned SrcReg;
353 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000354 } RegShiftedImm;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000355 struct {
356 unsigned Imm;
357 } RotImm;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000358 struct {
359 unsigned LSB;
360 unsigned Width;
361 } Bitfield;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000362 };
Jim Grosbach16c74252010-10-29 14:46:02 +0000363
Bill Wendling146018f2010-11-06 21:42:12 +0000364 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
365public:
Sean Callanan76264762010-04-02 22:27:05 +0000366 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
367 Kind = o.Kind;
368 StartLoc = o.StartLoc;
369 EndLoc = o.EndLoc;
370 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000371 case k_CondCode:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000372 CC = o.CC;
373 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000374 case k_ITCondMask:
Jim Grosbach89df9962011-08-26 21:43:41 +0000375 ITMask = o.ITMask;
376 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000377 case k_Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000378 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000379 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000380 case k_CCOut:
381 case k_Register:
Sean Callanan76264762010-04-02 22:27:05 +0000382 Reg = o.Reg;
383 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000384 case k_RegisterList:
385 case k_DPRRegisterList:
386 case k_SPRRegisterList:
Bill Wendling24d22d22010-11-18 21:50:54 +0000387 Registers = o.Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000388 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000389 case k_CoprocNum:
390 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000391 Cop = o.Cop;
392 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000393 case k_Immediate:
Sean Callanan76264762010-04-02 22:27:05 +0000394 Imm = o.Imm;
395 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000396 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +0000397 FPImm = o.FPImm;
398 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000399 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000400 MBOpt = o.MBOpt;
401 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000402 case k_Memory:
Jim Grosbache53c87b2011-10-11 15:59:20 +0000403 Memory = o.Memory;
Sean Callanan76264762010-04-02 22:27:05 +0000404 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000405 case k_PostIndexRegister:
Jim Grosbach7ce05792011-08-03 23:50:40 +0000406 PostIdxReg = o.PostIdxReg;
407 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000408 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000409 MMask = o.MMask;
410 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000411 case k_ProcIFlags:
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000412 IFlags = o.IFlags;
Owen Anderson00828302011-03-18 22:50:18 +0000413 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000414 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +0000415 ShifterImm = o.ShifterImm;
Owen Anderson00828302011-03-18 22:50:18 +0000416 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000417 case k_ShiftedRegister:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000418 RegShiftedReg = o.RegShiftedReg;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000419 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000420 case k_ShiftedImmediate:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000421 RegShiftedImm = o.RegShiftedImm;
Owen Anderson92a20222011-07-21 18:54:16 +0000422 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000423 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000424 RotImm = o.RotImm;
425 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000426 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000427 Bitfield = o.Bitfield;
428 break;
Jim Grosbach460a9052011-10-07 23:56:00 +0000429 case k_VectorIndex:
430 VectorIndex = o.VectorIndex;
431 break;
Sean Callanan76264762010-04-02 22:27:05 +0000432 }
433 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000434
Sean Callanan76264762010-04-02 22:27:05 +0000435 /// getStartLoc - Get the location of the first token of this operand.
436 SMLoc getStartLoc() const { return StartLoc; }
437 /// getEndLoc - Get the location of the last token of this operand.
438 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000439
Daniel Dunbar8462b302010-08-11 06:36:53 +0000440 ARMCC::CondCodes getCondCode() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000441 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000442 return CC.Val;
443 }
444
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000445 unsigned getCoproc() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000446 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000447 return Cop.Val;
448 }
449
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000450 StringRef getToken() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000451 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000452 return StringRef(Tok.Data, Tok.Length);
453 }
454
455 unsigned getReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000456 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling7729e062010-11-09 22:44:22 +0000457 return Reg.RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000458 }
459
Bill Wendling5fa22a12010-11-09 23:28:44 +0000460 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000461 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
462 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling24d22d22010-11-18 21:50:54 +0000463 return Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000464 }
465
Kevin Enderbycfe07242009-10-13 22:19:02 +0000466 const MCExpr *getImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000467 assert(Kind == k_Immediate && "Invalid access!");
Kevin Enderbycfe07242009-10-13 22:19:02 +0000468 return Imm.Val;
469 }
470
Jim Grosbach9d390362011-10-03 23:38:36 +0000471 unsigned getFPImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000472 assert(Kind == k_FPImmediate && "Invalid access!");
Jim Grosbach9d390362011-10-03 23:38:36 +0000473 return FPImm.Val;
474 }
475
Jim Grosbach460a9052011-10-07 23:56:00 +0000476 unsigned getVectorIndex() const {
477 assert(Kind == k_VectorIndex && "Invalid access!");
478 return VectorIndex.Val;
479 }
480
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000481 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000482 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000483 return MBOpt.Val;
484 }
485
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000486 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000487 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000488 return IFlags.Val;
489 }
490
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000491 unsigned getMSRMask() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000492 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000493 return MMask.Val;
494 }
495
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000496 bool isCoprocNum() const { return Kind == k_CoprocNum; }
497 bool isCoprocReg() const { return Kind == k_CoprocReg; }
498 bool isCondCode() const { return Kind == k_CondCode; }
499 bool isCCOut() const { return Kind == k_CCOut; }
500 bool isITMask() const { return Kind == k_ITCondMask; }
501 bool isITCondCode() const { return Kind == k_CondCode; }
502 bool isImm() const { return Kind == k_Immediate; }
503 bool isFPImm() const { return Kind == k_FPImmediate; }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000504 bool isImm8s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000505 if (Kind != k_Immediate)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000506 return false;
507 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
508 if (!CE) return false;
509 int64_t Value = CE->getValue();
510 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
511 }
Jim Grosbach72f39f82011-08-24 21:22:15 +0000512 bool isImm0_1020s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000513 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000514 return false;
515 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
516 if (!CE) return false;
517 int64_t Value = CE->getValue();
518 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
519 }
520 bool isImm0_508s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000521 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000522 return false;
523 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
524 if (!CE) return false;
525 int64_t Value = CE->getValue();
526 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
527 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000528 bool isImm0_255() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000529 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000530 return false;
531 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
532 if (!CE) return false;
533 int64_t Value = CE->getValue();
534 return Value >= 0 && Value < 256;
535 }
Jim Grosbach83ab0702011-07-13 22:01:08 +0000536 bool isImm0_7() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000537 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +0000538 return false;
539 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
540 if (!CE) return false;
541 int64_t Value = CE->getValue();
542 return Value >= 0 && Value < 8;
543 }
544 bool isImm0_15() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000545 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +0000546 return false;
547 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
548 if (!CE) return false;
549 int64_t Value = CE->getValue();
550 return Value >= 0 && Value < 16;
551 }
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000552 bool isImm0_31() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000553 if (Kind != k_Immediate)
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000554 return false;
555 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
556 if (!CE) return false;
557 int64_t Value = CE->getValue();
558 return Value >= 0 && Value < 32;
559 }
Jim Grosbachf4943352011-07-25 23:09:14 +0000560 bool isImm1_16() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000561 if (Kind != k_Immediate)
Jim Grosbachf4943352011-07-25 23:09:14 +0000562 return false;
563 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
564 if (!CE) return false;
565 int64_t Value = CE->getValue();
566 return Value > 0 && Value < 17;
567 }
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000568 bool isImm1_32() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000569 if (Kind != k_Immediate)
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000570 return false;
571 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
572 if (!CE) return false;
573 int64_t Value = CE->getValue();
574 return Value > 0 && Value < 33;
575 }
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000576 bool isImm0_65535() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000577 if (Kind != k_Immediate)
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000578 return false;
579 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
580 if (!CE) return false;
581 int64_t Value = CE->getValue();
582 return Value >= 0 && Value < 65536;
583 }
Jim Grosbachffa32252011-07-19 19:13:28 +0000584 bool isImm0_65535Expr() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000585 if (Kind != k_Immediate)
Jim Grosbachffa32252011-07-19 19:13:28 +0000586 return false;
587 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
588 // If it's not a constant expression, it'll generate a fixup and be
589 // handled later.
590 if (!CE) return true;
591 int64_t Value = CE->getValue();
592 return Value >= 0 && Value < 65536;
593 }
Jim Grosbached838482011-07-26 16:24:27 +0000594 bool isImm24bit() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000595 if (Kind != k_Immediate)
Jim Grosbached838482011-07-26 16:24:27 +0000596 return false;
597 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
598 if (!CE) return false;
599 int64_t Value = CE->getValue();
600 return Value >= 0 && Value <= 0xffffff;
601 }
Jim Grosbach70939ee2011-08-17 21:51:27 +0000602 bool isImmThumbSR() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000603 if (Kind != k_Immediate)
Jim Grosbach70939ee2011-08-17 21:51:27 +0000604 return false;
605 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
606 if (!CE) return false;
607 int64_t Value = CE->getValue();
608 return Value > 0 && Value < 33;
609 }
Jim Grosbachf6c05252011-07-21 17:23:04 +0000610 bool isPKHLSLImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000611 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000612 return false;
613 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
614 if (!CE) return false;
615 int64_t Value = CE->getValue();
616 return Value >= 0 && Value < 32;
617 }
618 bool isPKHASRImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000619 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000620 return false;
621 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
622 if (!CE) return false;
623 int64_t Value = CE->getValue();
624 return Value > 0 && Value <= 32;
625 }
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000626 bool isARMSOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000627 if (Kind != k_Immediate)
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000628 return false;
629 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
630 if (!CE) return false;
631 int64_t Value = CE->getValue();
632 return ARM_AM::getSOImmVal(Value) != -1;
633 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000634 bool isT2SOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000635 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000636 return false;
637 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
638 if (!CE) return false;
639 int64_t Value = CE->getValue();
640 return ARM_AM::getT2SOImmVal(Value) != -1;
641 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000642 bool isSetEndImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000643 if (Kind != k_Immediate)
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000644 return false;
645 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
646 if (!CE) return false;
647 int64_t Value = CE->getValue();
648 return Value == 1 || Value == 0;
649 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000650 bool isReg() const { return Kind == k_Register; }
651 bool isRegList() const { return Kind == k_RegisterList; }
652 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
653 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
654 bool isToken() const { return Kind == k_Token; }
655 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
656 bool isMemory() const { return Kind == k_Memory; }
657 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
658 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
659 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
660 bool isRotImm() const { return Kind == k_RotateImmediate; }
661 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
662 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000663 bool isPostIdxReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000664 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy == ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000665 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000666 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000667 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000668 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000669 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000670 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
671 (alignOK || Memory.Alignment == 0);
672 }
673 bool isAlignedMemory() const {
674 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000675 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000676 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000677 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000678 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000679 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000680 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000681 if (!Memory.OffsetImm) return true;
682 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000683 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000684 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000685 bool isAM2OffsetImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000686 if (Kind != k_Immediate)
Jim Grosbach039c2e12011-08-04 23:01:30 +0000687 return false;
688 // Immediate offset in range [-4095, 4095].
689 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
690 if (!CE) return false;
691 int64_t Val = CE->getValue();
692 return Val > -4096 && Val < 4096;
693 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000694 bool isAddrMode3() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000695 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000696 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000697 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000698 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000699 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000700 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000701 if (!Memory.OffsetImm) return true;
702 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000703 return Val > -256 && Val < 256;
704 }
705 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000706 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000707 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000708 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000709 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
710 // Immediate offset in range [-255, 255].
711 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
712 if (!CE) return false;
713 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000714 // Special case, #-0 is INT32_MIN.
715 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000716 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000717 bool isAddrMode5() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000718 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000719 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000720 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000721 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000722 if (!Memory.OffsetImm) return true;
723 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000724 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
725 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000726 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000727 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000728 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000729 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000730 return false;
731 return true;
732 }
733 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000734 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000735 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
736 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000737 return false;
738 return true;
739 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000740 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000741 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000742 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000743 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000744 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000745 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000746 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
747 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000748 return false;
749 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000750 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000751 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000752 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000753 return false;
754 return true;
755 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000756 bool isMemThumbRR() const {
757 // Thumb reg+reg addressing is simple. Just two registers, a base and
758 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000759 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000760 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000761 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000762 return isARMLowRegister(Memory.BaseRegNum) &&
763 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000764 }
765 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000766 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000767 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000768 return false;
769 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000770 if (!Memory.OffsetImm) return true;
771 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000772 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
773 }
Jim Grosbach38466302011-08-19 18:55:51 +0000774 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000775 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000776 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000777 return false;
778 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000779 if (!Memory.OffsetImm) return true;
780 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +0000781 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
782 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000783 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000784 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000785 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000786 return false;
787 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000788 if (!Memory.OffsetImm) return true;
789 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000790 return Val >= 0 && Val <= 31;
791 }
Jim Grosbachecd85892011-08-19 18:13:48 +0000792 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000793 if (!isMemory() || Memory.OffsetRegNum != 0 ||
794 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +0000795 return false;
796 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000797 if (!Memory.OffsetImm) return true;
798 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000799 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000800 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000801 bool isMemImm8s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000802 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000803 return false;
804 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000805 if (!Memory.OffsetImm) return true;
806 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +0000807 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
808 }
Jim Grosbachb6aed502011-09-09 18:37:27 +0000809 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000810 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +0000811 return false;
812 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000813 if (!Memory.OffsetImm) return true;
814 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +0000815 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
816 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000817 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000818 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000819 return false;
820 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000821 if (!Memory.OffsetImm) return true;
822 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +0000823 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000824 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000825 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000826 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000827 return false;
828 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000829 if (!Memory.OffsetImm) return true;
830 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000831 return Val >= 0 && Val < 256;
832 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000833 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000834 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000835 return false;
836 // Immediate offset in range [-255, -1].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000837 if (!Memory.OffsetImm) return true;
838 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000839 return Val > -256 && Val < 0;
840 }
841 bool isMemUImm12Offset() const {
842 // If we have an immediate that's not a constant, treat it as a label
843 // reference needing a fixup. If it is a constant, it's something else
844 // and we reject it.
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000845 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000846 return true;
847
Jim Grosbach57dcb852011-10-11 17:29:55 +0000848 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000849 return false;
850 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000851 if (!Memory.OffsetImm) return true;
852 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000853 return (Val >= 0 && Val < 4096);
854 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000855 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +0000856 // If we have an immediate that's not a constant, treat it as a label
857 // reference needing a fixup. If it is a constant, it's something else
858 // and we reject it.
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000859 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +0000860 return true;
861
Jim Grosbach57dcb852011-10-11 17:29:55 +0000862 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000863 return false;
864 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000865 if (!Memory.OffsetImm) return true;
866 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000867 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000868 }
869 bool isPostIdxImm8() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000870 if (Kind != k_Immediate)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000871 return false;
872 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
873 if (!CE) return false;
874 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +0000875 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000876 }
877
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000878 bool isMSRMask() const { return Kind == k_MSRMask; }
879 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000880
Jim Grosbach460a9052011-10-07 23:56:00 +0000881 bool isVectorIndex8() const {
882 if (Kind != k_VectorIndex) return false;
883 return VectorIndex.Val < 8;
884 }
885 bool isVectorIndex16() const {
886 if (Kind != k_VectorIndex) return false;
887 return VectorIndex.Val < 4;
888 }
889 bool isVectorIndex32() const {
890 if (Kind != k_VectorIndex) return false;
891 return VectorIndex.Val < 2;
892 }
893
894
895
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000896 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +0000897 // Add as immediates when possible. Null MCExpr = 0.
898 if (Expr == 0)
899 Inst.addOperand(MCOperand::CreateImm(0));
900 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000901 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
902 else
903 Inst.addOperand(MCOperand::CreateExpr(Expr));
904 }
905
Daniel Dunbar8462b302010-08-11 06:36:53 +0000906 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +0000907 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000908 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +0000909 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
910 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +0000911 }
912
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000913 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
914 assert(N == 1 && "Invalid number of operands!");
915 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
916 }
917
Jim Grosbach89df9962011-08-26 21:43:41 +0000918 void addITMaskOperands(MCInst &Inst, unsigned N) const {
919 assert(N == 1 && "Invalid number of operands!");
920 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
921 }
922
923 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
924 assert(N == 1 && "Invalid number of operands!");
925 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
926 }
927
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000928 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
929 assert(N == 1 && "Invalid number of operands!");
930 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
931 }
932
Jim Grosbachd67641b2010-12-06 18:21:12 +0000933 void addCCOutOperands(MCInst &Inst, unsigned N) const {
934 assert(N == 1 && "Invalid number of operands!");
935 Inst.addOperand(MCOperand::CreateReg(getReg()));
936 }
937
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000938 void addRegOperands(MCInst &Inst, unsigned N) const {
939 assert(N == 1 && "Invalid number of operands!");
940 Inst.addOperand(MCOperand::CreateReg(getReg()));
941 }
942
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000943 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +0000944 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000945 assert(isRegShiftedReg() && "addRegShiftedRegOperands() on non RegShiftedReg!");
946 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
947 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +0000948 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000949 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +0000950 }
951
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000952 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +0000953 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000954 assert(isRegShiftedImm() && "addRegShiftedImmOperands() on non RegShiftedImm!");
955 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +0000956 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000957 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +0000958 }
959
Jim Grosbach580f4a92011-07-25 22:20:28 +0000960 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +0000961 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +0000962 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
963 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +0000964 }
965
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000966 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +0000967 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +0000968 const SmallVectorImpl<unsigned> &RegList = getRegList();
969 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +0000970 I = RegList.begin(), E = RegList.end(); I != E; ++I)
971 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000972 }
973
Bill Wendling0f630752010-11-17 04:32:08 +0000974 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
975 addRegListOperands(Inst, N);
976 }
977
978 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
979 addRegListOperands(Inst, N);
980 }
981
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000982 void addRotImmOperands(MCInst &Inst, unsigned N) const {
983 assert(N == 1 && "Invalid number of operands!");
984 // Encoded as val>>3. The printer handles display as 8, 16, 24.
985 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
986 }
987
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000988 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
989 assert(N == 1 && "Invalid number of operands!");
990 // Munge the lsb/width into a bitfield mask.
991 unsigned lsb = Bitfield.LSB;
992 unsigned width = Bitfield.Width;
993 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
994 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
995 (32 - (lsb + width)));
996 Inst.addOperand(MCOperand::CreateImm(Mask));
997 }
998
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000999 void addImmOperands(MCInst &Inst, unsigned N) const {
1000 assert(N == 1 && "Invalid number of operands!");
1001 addExpr(Inst, getImm());
1002 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001003
Jim Grosbach9d390362011-10-03 23:38:36 +00001004 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1005 assert(N == 1 && "Invalid number of operands!");
1006 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1007 }
1008
Jim Grosbacha77295d2011-09-08 22:07:06 +00001009 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1010 assert(N == 1 && "Invalid number of operands!");
1011 // FIXME: We really want to scale the value here, but the LDRD/STRD
1012 // instruction don't encode operands that way yet.
1013 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1014 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1015 }
1016
Jim Grosbach72f39f82011-08-24 21:22:15 +00001017 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1018 assert(N == 1 && "Invalid number of operands!");
1019 // The immediate is scaled by four in the encoding and is stored
1020 // in the MCInst as such. Lop off the low two bits here.
1021 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1022 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1023 }
1024
1025 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1026 assert(N == 1 && "Invalid number of operands!");
1027 // The immediate is scaled by four in the encoding and is stored
1028 // in the MCInst as such. Lop off the low two bits here.
1029 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1030 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1031 }
1032
Jim Grosbach6b8f1e32011-06-27 23:54:06 +00001033 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1034 assert(N == 1 && "Invalid number of operands!");
1035 addExpr(Inst, getImm());
1036 }
1037
Jim Grosbach83ab0702011-07-13 22:01:08 +00001038 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1039 assert(N == 1 && "Invalid number of operands!");
1040 addExpr(Inst, getImm());
1041 }
1042
1043 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1044 assert(N == 1 && "Invalid number of operands!");
1045 addExpr(Inst, getImm());
1046 }
1047
Jim Grosbach7c6e42e2011-07-21 23:26:25 +00001048 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1049 assert(N == 1 && "Invalid number of operands!");
1050 addExpr(Inst, getImm());
1051 }
1052
Jim Grosbachf4943352011-07-25 23:09:14 +00001053 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1054 assert(N == 1 && "Invalid number of operands!");
1055 // The constant encodes as the immediate-1, and we store in the instruction
1056 // the bits as encoded, so subtract off one here.
1057 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1058 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1059 }
1060
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001061 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1062 assert(N == 1 && "Invalid number of operands!");
1063 // The constant encodes as the immediate-1, and we store in the instruction
1064 // the bits as encoded, so subtract off one here.
1065 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1066 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1067 }
1068
Jim Grosbachfff76ee2011-07-13 20:10:10 +00001069 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1070 assert(N == 1 && "Invalid number of operands!");
1071 addExpr(Inst, getImm());
1072 }
1073
Jim Grosbachffa32252011-07-19 19:13:28 +00001074 void addImm0_65535ExprOperands(MCInst &Inst, unsigned N) const {
1075 assert(N == 1 && "Invalid number of operands!");
1076 addExpr(Inst, getImm());
1077 }
1078
Jim Grosbached838482011-07-26 16:24:27 +00001079 void addImm24bitOperands(MCInst &Inst, unsigned N) const {
1080 assert(N == 1 && "Invalid number of operands!");
1081 addExpr(Inst, getImm());
1082 }
1083
Jim Grosbach70939ee2011-08-17 21:51:27 +00001084 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1085 assert(N == 1 && "Invalid number of operands!");
1086 // The constant encodes as the immediate, except for 32, which encodes as
1087 // zero.
1088 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1089 unsigned Imm = CE->getValue();
1090 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1091 }
1092
Jim Grosbachf6c05252011-07-21 17:23:04 +00001093 void addPKHLSLImmOperands(MCInst &Inst, unsigned N) const {
1094 assert(N == 1 && "Invalid number of operands!");
1095 addExpr(Inst, getImm());
1096 }
1097
1098 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1099 assert(N == 1 && "Invalid number of operands!");
1100 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1101 // the instruction as well.
1102 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1103 int Val = CE->getValue();
1104 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1105 }
1106
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +00001107 void addARMSOImmOperands(MCInst &Inst, unsigned N) const {
1108 assert(N == 1 && "Invalid number of operands!");
1109 addExpr(Inst, getImm());
1110 }
1111
Jim Grosbach6b8f1e32011-06-27 23:54:06 +00001112 void addT2SOImmOperands(MCInst &Inst, unsigned N) const {
1113 assert(N == 1 && "Invalid number of operands!");
1114 addExpr(Inst, getImm());
1115 }
1116
Jim Grosbachc27d4f92011-07-22 17:44:50 +00001117 void addSetEndImmOperands(MCInst &Inst, unsigned N) const {
1118 assert(N == 1 && "Invalid number of operands!");
1119 addExpr(Inst, getImm());
1120 }
1121
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001122 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1123 assert(N == 1 && "Invalid number of operands!");
1124 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1125 }
1126
Jim Grosbach7ce05792011-08-03 23:50:40 +00001127 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1128 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001129 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001130 }
1131
Jim Grosbach57dcb852011-10-11 17:29:55 +00001132 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1133 assert(N == 2 && "Invalid number of operands!");
1134 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1135 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1136 }
1137
Jim Grosbach7ce05792011-08-03 23:50:40 +00001138 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1139 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001140 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1141 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001142 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1143 // Special case for #-0
1144 if (Val == INT32_MIN) Val = 0;
1145 if (Val < 0) Val = -Val;
1146 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1147 } else {
1148 // For register offset, we encode the shift type and negation flag
1149 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001150 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1151 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001152 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001153 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1154 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001155 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001156 }
1157
Jim Grosbach039c2e12011-08-04 23:01:30 +00001158 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1159 assert(N == 2 && "Invalid number of operands!");
1160 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1161 assert(CE && "non-constant AM2OffsetImm operand!");
1162 int32_t Val = CE->getValue();
1163 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1164 // Special case for #-0
1165 if (Val == INT32_MIN) Val = 0;
1166 if (Val < 0) Val = -Val;
1167 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1168 Inst.addOperand(MCOperand::CreateReg(0));
1169 Inst.addOperand(MCOperand::CreateImm(Val));
1170 }
1171
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001172 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1173 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001174 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1175 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001176 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1177 // Special case for #-0
1178 if (Val == INT32_MIN) Val = 0;
1179 if (Val < 0) Val = -Val;
1180 Val = ARM_AM::getAM3Opc(AddSub, Val);
1181 } else {
1182 // For register offset, we encode the shift type and negation flag
1183 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001184 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001185 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001186 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1187 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001188 Inst.addOperand(MCOperand::CreateImm(Val));
1189 }
1190
1191 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1192 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001193 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001194 int32_t Val =
1195 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1196 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1197 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001198 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001199 }
1200
1201 // Constant offset.
1202 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1203 int32_t Val = CE->getValue();
1204 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1205 // Special case for #-0
1206 if (Val == INT32_MIN) Val = 0;
1207 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001208 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001209 Inst.addOperand(MCOperand::CreateReg(0));
1210 Inst.addOperand(MCOperand::CreateImm(Val));
1211 }
1212
Jim Grosbach7ce05792011-08-03 23:50:40 +00001213 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1214 assert(N == 2 && "Invalid number of operands!");
1215 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001216 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001217 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1218 // Special case for #-0
1219 if (Val == INT32_MIN) Val = 0;
1220 if (Val < 0) Val = -Val;
1221 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001222 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001223 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001224 }
1225
Jim Grosbacha77295d2011-09-08 22:07:06 +00001226 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1227 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001228 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1229 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001230 Inst.addOperand(MCOperand::CreateImm(Val));
1231 }
1232
Jim Grosbachb6aed502011-09-09 18:37:27 +00001233 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1234 assert(N == 2 && "Invalid number of operands!");
1235 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001236 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1237 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001238 Inst.addOperand(MCOperand::CreateImm(Val));
1239 }
1240
Jim Grosbach7ce05792011-08-03 23:50:40 +00001241 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1242 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001243 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1244 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001245 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001246 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001247
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001248 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1249 addMemImm8OffsetOperands(Inst, N);
1250 }
1251
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001252 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001253 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001254 }
1255
1256 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1257 assert(N == 2 && "Invalid number of operands!");
1258 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001259 if (Kind == k_Immediate) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001260 addExpr(Inst, getImm());
1261 Inst.addOperand(MCOperand::CreateImm(0));
1262 return;
1263 }
1264
1265 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001266 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1267 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001268 Inst.addOperand(MCOperand::CreateImm(Val));
1269 }
1270
Jim Grosbach7ce05792011-08-03 23:50:40 +00001271 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1272 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001273 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001274 if (Kind == k_Immediate) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001275 addExpr(Inst, getImm());
1276 Inst.addOperand(MCOperand::CreateImm(0));
1277 return;
1278 }
1279
1280 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001281 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1282 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001283 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001284 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001285
Jim Grosbach7f739be2011-09-19 22:21:13 +00001286 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1287 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001288 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1289 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001290 }
1291
1292 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1293 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001294 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1295 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001296 }
1297
Jim Grosbach7ce05792011-08-03 23:50:40 +00001298 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1299 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001300 unsigned Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1301 Memory.ShiftImm, Memory.ShiftType);
1302 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1303 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001304 Inst.addOperand(MCOperand::CreateImm(Val));
1305 }
1306
Jim Grosbachab899c12011-09-07 23:10:15 +00001307 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1308 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001309 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1310 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1311 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001312 }
1313
Jim Grosbach7ce05792011-08-03 23:50:40 +00001314 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1315 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001316 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1317 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001318 }
1319
Jim Grosbach60f91a32011-08-19 17:55:24 +00001320 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1321 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001322 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1323 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001324 Inst.addOperand(MCOperand::CreateImm(Val));
1325 }
1326
Jim Grosbach38466302011-08-19 18:55:51 +00001327 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1328 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001329 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1330 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001331 Inst.addOperand(MCOperand::CreateImm(Val));
1332 }
1333
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001334 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1335 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001336 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1337 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001338 Inst.addOperand(MCOperand::CreateImm(Val));
1339 }
1340
Jim Grosbachecd85892011-08-19 18:13:48 +00001341 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1342 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001343 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1344 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001345 Inst.addOperand(MCOperand::CreateImm(Val));
1346 }
1347
Jim Grosbach7ce05792011-08-03 23:50:40 +00001348 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1349 assert(N == 1 && "Invalid number of operands!");
1350 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1351 assert(CE && "non-constant post-idx-imm8 operand!");
1352 int Imm = CE->getValue();
1353 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001354 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001355 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1356 Inst.addOperand(MCOperand::CreateImm(Imm));
1357 }
1358
1359 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1360 assert(N == 2 && "Invalid number of operands!");
1361 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001362 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1363 }
1364
1365 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1366 assert(N == 2 && "Invalid number of operands!");
1367 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1368 // The sign, shift type, and shift amount are encoded in a single operand
1369 // using the AM2 encoding helpers.
1370 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1371 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1372 PostIdxReg.ShiftTy);
1373 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001374 }
1375
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001376 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1377 assert(N == 1 && "Invalid number of operands!");
1378 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1379 }
1380
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001381 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1382 assert(N == 1 && "Invalid number of operands!");
1383 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1384 }
1385
Jim Grosbach460a9052011-10-07 23:56:00 +00001386 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1387 assert(N == 1 && "Invalid number of operands!");
1388 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1389 }
1390
1391 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1392 assert(N == 1 && "Invalid number of operands!");
1393 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1394 }
1395
1396 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1397 assert(N == 1 && "Invalid number of operands!");
1398 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1399 }
1400
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001401 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001402
Jim Grosbach89df9962011-08-26 21:43:41 +00001403 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001404 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001405 Op->ITMask.Mask = Mask;
1406 Op->StartLoc = S;
1407 Op->EndLoc = S;
1408 return Op;
1409 }
1410
Chris Lattner3a697562010-10-28 17:20:03 +00001411 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001412 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001413 Op->CC.Val = CC;
1414 Op->StartLoc = S;
1415 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001416 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001417 }
1418
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001419 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001420 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001421 Op->Cop.Val = CopVal;
1422 Op->StartLoc = S;
1423 Op->EndLoc = S;
1424 return Op;
1425 }
1426
1427 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001428 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001429 Op->Cop.Val = CopVal;
1430 Op->StartLoc = S;
1431 Op->EndLoc = S;
1432 return Op;
1433 }
1434
Jim Grosbachd67641b2010-12-06 18:21:12 +00001435 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001436 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00001437 Op->Reg.RegNum = RegNum;
1438 Op->StartLoc = S;
1439 Op->EndLoc = S;
1440 return Op;
1441 }
1442
Chris Lattner3a697562010-10-28 17:20:03 +00001443 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001444 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00001445 Op->Tok.Data = Str.data();
1446 Op->Tok.Length = Str.size();
1447 Op->StartLoc = S;
1448 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001449 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001450 }
1451
Bill Wendling50d0f582010-11-18 23:43:05 +00001452 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001453 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00001454 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001455 Op->StartLoc = S;
1456 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001457 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001458 }
1459
Jim Grosbache8606dc2011-07-13 17:50:29 +00001460 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1461 unsigned SrcReg,
1462 unsigned ShiftReg,
1463 unsigned ShiftImm,
1464 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001465 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001466 Op->RegShiftedReg.ShiftTy = ShTy;
1467 Op->RegShiftedReg.SrcReg = SrcReg;
1468 Op->RegShiftedReg.ShiftReg = ShiftReg;
1469 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001470 Op->StartLoc = S;
1471 Op->EndLoc = E;
1472 return Op;
1473 }
1474
Owen Anderson92a20222011-07-21 18:54:16 +00001475 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1476 unsigned SrcReg,
1477 unsigned ShiftImm,
1478 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001479 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001480 Op->RegShiftedImm.ShiftTy = ShTy;
1481 Op->RegShiftedImm.SrcReg = SrcReg;
1482 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00001483 Op->StartLoc = S;
1484 Op->EndLoc = E;
1485 return Op;
1486 }
1487
Jim Grosbach580f4a92011-07-25 22:20:28 +00001488 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001489 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001490 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00001491 Op->ShifterImm.isASR = isASR;
1492 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00001493 Op->StartLoc = S;
1494 Op->EndLoc = E;
1495 return Op;
1496 }
1497
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001498 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001499 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001500 Op->RotImm.Imm = Imm;
1501 Op->StartLoc = S;
1502 Op->EndLoc = E;
1503 return Op;
1504 }
1505
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001506 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1507 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001508 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001509 Op->Bitfield.LSB = LSB;
1510 Op->Bitfield.Width = Width;
1511 Op->StartLoc = S;
1512 Op->EndLoc = E;
1513 return Op;
1514 }
1515
Bill Wendling7729e062010-11-09 22:44:22 +00001516 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00001517 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001518 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001519 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001520
Jim Grosbachd300b942011-09-13 22:56:44 +00001521 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001522 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00001523 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00001524 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001525 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001526
1527 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00001528 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001529 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00001530 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00001531 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001532 Op->StartLoc = StartLoc;
1533 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00001534 return Op;
1535 }
1536
Jim Grosbach460a9052011-10-07 23:56:00 +00001537 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
1538 MCContext &Ctx) {
1539 ARMOperand *Op = new ARMOperand(k_VectorIndex);
1540 Op->VectorIndex.Val = Idx;
1541 Op->StartLoc = S;
1542 Op->EndLoc = E;
1543 return Op;
1544 }
1545
Chris Lattner3a697562010-10-28 17:20:03 +00001546 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001547 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00001548 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00001549 Op->StartLoc = S;
1550 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001551 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00001552 }
1553
Jim Grosbach9d390362011-10-03 23:38:36 +00001554 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001555 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbach9d390362011-10-03 23:38:36 +00001556 Op->FPImm.Val = Val;
1557 Op->StartLoc = S;
1558 Op->EndLoc = S;
1559 return Op;
1560 }
1561
Jim Grosbach7ce05792011-08-03 23:50:40 +00001562 static ARMOperand *CreateMem(unsigned BaseRegNum,
1563 const MCConstantExpr *OffsetImm,
1564 unsigned OffsetRegNum,
1565 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00001566 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00001567 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001568 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00001569 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001570 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001571 Op->Memory.BaseRegNum = BaseRegNum;
1572 Op->Memory.OffsetImm = OffsetImm;
1573 Op->Memory.OffsetRegNum = OffsetRegNum;
1574 Op->Memory.ShiftType = ShiftType;
1575 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00001576 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001577 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001578 Op->StartLoc = S;
1579 Op->EndLoc = E;
1580 return Op;
1581 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001582
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001583 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
1584 ARM_AM::ShiftOpc ShiftTy,
1585 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001586 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001587 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001588 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001589 Op->PostIdxReg.isAdd = isAdd;
1590 Op->PostIdxReg.ShiftTy = ShiftTy;
1591 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00001592 Op->StartLoc = S;
1593 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001594 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001595 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001596
1597 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001598 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001599 Op->MBOpt.Val = Opt;
1600 Op->StartLoc = S;
1601 Op->EndLoc = S;
1602 return Op;
1603 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001604
1605 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001606 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001607 Op->IFlags.Val = IFlags;
1608 Op->StartLoc = S;
1609 Op->EndLoc = S;
1610 return Op;
1611 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001612
1613 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001614 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001615 Op->MMask.Val = MMask;
1616 Op->StartLoc = S;
1617 Op->EndLoc = S;
1618 return Op;
1619 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001620};
1621
1622} // end anonymous namespace.
1623
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001624void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001625 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001626 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +00001627 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
1628 << ") >";
1629 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001630 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00001631 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001632 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001633 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00001634 OS << "<ccout " << getReg() << ">";
1635 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001636 case k_ITCondMask: {
Jim Grosbach89df9962011-08-26 21:43:41 +00001637 static char MaskStr[][6] = { "()", "(t)", "(e)", "(tt)", "(et)", "(te)",
1638 "(ee)", "(ttt)", "(ett)", "(tet)", "(eet)", "(tte)", "(ete)",
1639 "(tee)", "(eee)" };
1640 assert((ITMask.Mask & 0xf) == ITMask.Mask);
1641 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
1642 break;
1643 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001644 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001645 OS << "<coprocessor number: " << getCoproc() << ">";
1646 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001647 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001648 OS << "<coprocessor register: " << getCoproc() << ">";
1649 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001650 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001651 OS << "<mask: " << getMSRMask() << ">";
1652 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001653 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001654 getImm()->print(OS);
1655 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001656 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001657 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
1658 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001659 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001660 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00001661 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001662 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001663 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001664 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001665 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
1666 << PostIdxReg.RegNum;
1667 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
1668 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
1669 << PostIdxReg.ShiftImm;
1670 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00001671 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001672 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001673 OS << "<ARM_PROC::";
1674 unsigned IFlags = getProcIFlags();
1675 for (int i=2; i >= 0; --i)
1676 if (IFlags & (1 << i))
1677 OS << ARM_PROC::IFlagsToString(1 << i);
1678 OS << ">";
1679 break;
1680 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001681 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00001682 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001683 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001684 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00001685 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
1686 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00001687 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001688 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00001689 OS << "<so_reg_reg "
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001690 << RegShiftedReg.SrcReg
1691 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedReg.ShiftImm))
1692 << ", " << RegShiftedReg.ShiftReg << ", "
1693 << ARM_AM::getSORegOffset(RegShiftedReg.ShiftImm)
Jim Grosbache8606dc2011-07-13 17:50:29 +00001694 << ">";
Owen Anderson00828302011-03-18 22:50:18 +00001695 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001696 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00001697 OS << "<so_reg_imm "
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001698 << RegShiftedImm.SrcReg
1699 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedImm.ShiftImm))
1700 << ", " << ARM_AM::getSORegOffset(RegShiftedImm.ShiftImm)
Owen Anderson92a20222011-07-21 18:54:16 +00001701 << ">";
1702 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001703 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001704 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
1705 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001706 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001707 OS << "<bitfield " << "lsb: " << Bitfield.LSB
1708 << ", width: " << Bitfield.Width << ">";
1709 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001710 case k_RegisterList:
1711 case k_DPRRegisterList:
1712 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00001713 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001714
Bill Wendling5fa22a12010-11-09 23:28:44 +00001715 const SmallVectorImpl<unsigned> &RegList = getRegList();
1716 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001717 I = RegList.begin(), E = RegList.end(); I != E; ) {
1718 OS << *I;
1719 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001720 }
1721
1722 OS << ">";
1723 break;
1724 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001725 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001726 OS << "'" << getToken() << "'";
1727 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00001728 case k_VectorIndex:
1729 OS << "<vectorindex " << getVectorIndex() << ">";
1730 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001731 }
1732}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001733
1734/// @name Auto-generated Match Functions
1735/// {
1736
1737static unsigned MatchRegisterName(StringRef Name);
1738
1739/// }
1740
Bob Wilson69df7232011-02-03 21:46:10 +00001741bool ARMAsmParser::ParseRegister(unsigned &RegNo,
1742 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00001743 RegNo = tryParseRegister();
Roman Divackybf755322011-01-27 17:14:22 +00001744
1745 return (RegNo == (unsigned)-1);
1746}
1747
Kevin Enderby9c41fa82009-10-30 22:55:57 +00001748/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00001749/// and if it is a register name the token is eaten and the register number is
1750/// returned. Otherwise return -1.
1751///
Jim Grosbach1355cf12011-07-26 17:10:22 +00001752int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00001753 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00001754 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00001755
Chris Lattnere5658fa2010-10-30 04:09:10 +00001756 // FIXME: Validate register for the current architecture; we have to do
1757 // validation later, so maybe there is no need for this here.
Owen Anderson0c9f2502011-01-13 22:50:36 +00001758 std::string upperCase = Tok.getString().str();
1759 std::string lowerCase = LowercaseString(upperCase);
1760 unsigned RegNum = MatchRegisterName(lowerCase);
1761 if (!RegNum) {
1762 RegNum = StringSwitch<unsigned>(lowerCase)
1763 .Case("r13", ARM::SP)
1764 .Case("r14", ARM::LR)
1765 .Case("r15", ARM::PC)
1766 .Case("ip", ARM::R12)
1767 .Default(0);
1768 }
1769 if (!RegNum) return -1;
Bob Wilson69df7232011-02-03 21:46:10 +00001770
Chris Lattnere5658fa2010-10-30 04:09:10 +00001771 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00001772
1773#if 0
1774 // Also check for an index operand. This is only legal for vector registers,
1775 // but that'll get caught OK in operand matching, so we don't need to
1776 // explicitly filter everything else out here.
1777 if (Parser.getTok().is(AsmToken::LBrac)) {
1778 SMLoc SIdx = Parser.getTok().getLoc();
1779 Parser.Lex(); // Eat left bracket token.
1780
1781 const MCExpr *ImmVal;
1782 SMLoc ExprLoc = Parser.getTok().getLoc();
1783 if (getParser().ParseExpression(ImmVal))
1784 return MatchOperand_ParseFail;
1785 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
1786 if (!MCE) {
1787 TokError("immediate value expected for vector index");
1788 return MatchOperand_ParseFail;
1789 }
1790
1791 SMLoc E = Parser.getTok().getLoc();
1792 if (Parser.getTok().isNot(AsmToken::RBrac)) {
1793 Error(E, "']' expected");
1794 return MatchOperand_ParseFail;
1795 }
1796
1797 Parser.Lex(); // Eat right bracket token.
1798
1799 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
1800 SIdx, E,
1801 getContext()));
1802 }
1803#endif
1804
Chris Lattnere5658fa2010-10-30 04:09:10 +00001805 return RegNum;
1806}
Jim Grosbachd4462a52010-11-01 16:44:21 +00001807
Jim Grosbach19906722011-07-13 18:49:30 +00001808// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
1809// If a recoverable error occurs, return 1. If an irrecoverable error
1810// occurs, return -1. An irrecoverable error is one where tokens have been
1811// consumed in the process of trying to parse the shifter (i.e., when it is
1812// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00001813int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00001814 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1815 SMLoc S = Parser.getTok().getLoc();
1816 const AsmToken &Tok = Parser.getTok();
1817 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
1818
1819 std::string upperCase = Tok.getString().str();
1820 std::string lowerCase = LowercaseString(upperCase);
1821 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
1822 .Case("lsl", ARM_AM::lsl)
1823 .Case("lsr", ARM_AM::lsr)
1824 .Case("asr", ARM_AM::asr)
1825 .Case("ror", ARM_AM::ror)
1826 .Case("rrx", ARM_AM::rrx)
1827 .Default(ARM_AM::no_shift);
1828
1829 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00001830 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00001831
Jim Grosbache8606dc2011-07-13 17:50:29 +00001832 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00001833
Jim Grosbache8606dc2011-07-13 17:50:29 +00001834 // The source register for the shift has already been added to the
1835 // operand list, so we need to pop it off and combine it into the shifted
1836 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00001837 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00001838 if (!PrevOp->isReg())
1839 return Error(PrevOp->getStartLoc(), "shift must be of a register");
1840 int SrcReg = PrevOp->getReg();
1841 int64_t Imm = 0;
1842 int ShiftReg = 0;
1843 if (ShiftTy == ARM_AM::rrx) {
1844 // RRX Doesn't have an explicit shift amount. The encoder expects
1845 // the shift register to be the same as the source register. Seems odd,
1846 // but OK.
1847 ShiftReg = SrcReg;
1848 } else {
1849 // Figure out if this is shifted by a constant or a register (for non-RRX).
1850 if (Parser.getTok().is(AsmToken::Hash)) {
1851 Parser.Lex(); // Eat hash.
1852 SMLoc ImmLoc = Parser.getTok().getLoc();
1853 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00001854 if (getParser().ParseExpression(ShiftExpr)) {
1855 Error(ImmLoc, "invalid immediate shift value");
1856 return -1;
1857 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00001858 // The expression must be evaluatable as an immediate.
1859 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00001860 if (!CE) {
1861 Error(ImmLoc, "invalid immediate shift value");
1862 return -1;
1863 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00001864 // Range check the immediate.
1865 // lsl, ror: 0 <= imm <= 31
1866 // lsr, asr: 0 <= imm <= 32
1867 Imm = CE->getValue();
1868 if (Imm < 0 ||
1869 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
1870 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00001871 Error(ImmLoc, "immediate shift value out of range");
1872 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001873 }
1874 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00001875 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00001876 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00001877 if (ShiftReg == -1) {
1878 Error (L, "expected immediate or register in shift operand");
1879 return -1;
1880 }
1881 } else {
1882 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00001883 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00001884 return -1;
1885 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00001886 }
1887
Owen Anderson92a20222011-07-21 18:54:16 +00001888 if (ShiftReg && ShiftTy != ARM_AM::rrx)
1889 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001890 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001891 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00001892 else
1893 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
1894 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00001895
Jim Grosbach19906722011-07-13 18:49:30 +00001896 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00001897}
1898
1899
Bill Wendling50d0f582010-11-18 23:43:05 +00001900/// Try to parse a register name. The token must be an Identifier when called.
1901/// If it's a register, an AsmOperand is created. Another AsmOperand is created
1902/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00001903///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00001904/// TODO this is likely to change to allow different register types and or to
1905/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00001906bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00001907tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00001908 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00001909 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00001910 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00001911 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00001912
Bill Wendling50d0f582010-11-18 23:43:05 +00001913 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001914
Chris Lattnere5658fa2010-10-30 04:09:10 +00001915 const AsmToken &ExclaimTok = Parser.getTok();
1916 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00001917 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
1918 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00001919 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00001920 return false;
1921 }
1922
1923 // Also check for an index operand. This is only legal for vector registers,
1924 // but that'll get caught OK in operand matching, so we don't need to
1925 // explicitly filter everything else out here.
1926 if (Parser.getTok().is(AsmToken::LBrac)) {
1927 SMLoc SIdx = Parser.getTok().getLoc();
1928 Parser.Lex(); // Eat left bracket token.
1929
1930 const MCExpr *ImmVal;
1931 SMLoc ExprLoc = Parser.getTok().getLoc();
1932 if (getParser().ParseExpression(ImmVal))
1933 return MatchOperand_ParseFail;
1934 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
1935 if (!MCE) {
1936 TokError("immediate value expected for vector index");
1937 return MatchOperand_ParseFail;
1938 }
1939
1940 SMLoc E = Parser.getTok().getLoc();
1941 if (Parser.getTok().isNot(AsmToken::RBrac)) {
1942 Error(E, "']' expected");
1943 return MatchOperand_ParseFail;
1944 }
1945
1946 Parser.Lex(); // Eat right bracket token.
1947
1948 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
1949 SIdx, E,
1950 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00001951 }
1952
Bill Wendling50d0f582010-11-18 23:43:05 +00001953 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001954}
1955
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001956/// MatchCoprocessorOperandName - Try to parse an coprocessor related
1957/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
1958/// "c5", ...
1959static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00001960 // Use the same layout as the tablegen'erated register name matcher. Ugly,
1961 // but efficient.
1962 switch (Name.size()) {
1963 default: break;
1964 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001965 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00001966 return -1;
1967 switch (Name[1]) {
1968 default: return -1;
1969 case '0': return 0;
1970 case '1': return 1;
1971 case '2': return 2;
1972 case '3': return 3;
1973 case '4': return 4;
1974 case '5': return 5;
1975 case '6': return 6;
1976 case '7': return 7;
1977 case '8': return 8;
1978 case '9': return 9;
1979 }
1980 break;
1981 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001982 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00001983 return -1;
1984 switch (Name[2]) {
1985 default: return -1;
1986 case '0': return 10;
1987 case '1': return 11;
1988 case '2': return 12;
1989 case '3': return 13;
1990 case '4': return 14;
1991 case '5': return 15;
1992 }
1993 break;
1994 }
1995
Owen Andersone4e5e2a2011-01-13 21:46:02 +00001996 return -1;
1997}
1998
Jim Grosbach89df9962011-08-26 21:43:41 +00001999/// parseITCondCode - Try to parse a condition code for an IT instruction.
2000ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2001parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2002 SMLoc S = Parser.getTok().getLoc();
2003 const AsmToken &Tok = Parser.getTok();
2004 if (!Tok.is(AsmToken::Identifier))
2005 return MatchOperand_NoMatch;
2006 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2007 .Case("eq", ARMCC::EQ)
2008 .Case("ne", ARMCC::NE)
2009 .Case("hs", ARMCC::HS)
2010 .Case("cs", ARMCC::HS)
2011 .Case("lo", ARMCC::LO)
2012 .Case("cc", ARMCC::LO)
2013 .Case("mi", ARMCC::MI)
2014 .Case("pl", ARMCC::PL)
2015 .Case("vs", ARMCC::VS)
2016 .Case("vc", ARMCC::VC)
2017 .Case("hi", ARMCC::HI)
2018 .Case("ls", ARMCC::LS)
2019 .Case("ge", ARMCC::GE)
2020 .Case("lt", ARMCC::LT)
2021 .Case("gt", ARMCC::GT)
2022 .Case("le", ARMCC::LE)
2023 .Case("al", ARMCC::AL)
2024 .Default(~0U);
2025 if (CC == ~0U)
2026 return MatchOperand_NoMatch;
2027 Parser.Lex(); // Eat the token.
2028
2029 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2030
2031 return MatchOperand_Success;
2032}
2033
Jim Grosbach43904292011-07-25 20:14:50 +00002034/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002035/// token must be an Identifier when called, and if it is a coprocessor
2036/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002037ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002038parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002039 SMLoc S = Parser.getTok().getLoc();
2040 const AsmToken &Tok = Parser.getTok();
2041 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2042
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002043 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002044 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002045 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002046
2047 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002048 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002049 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002050}
2051
Jim Grosbach43904292011-07-25 20:14:50 +00002052/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002053/// token must be an Identifier when called, and if it is a coprocessor
2054/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002055ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002056parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002057 SMLoc S = Parser.getTok().getLoc();
2058 const AsmToken &Tok = Parser.getTok();
2059 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2060
2061 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2062 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002063 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002064
2065 Parser.Lex(); // Eat identifier token.
2066 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002067 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002068}
2069
Jim Grosbachd0588e22011-09-14 18:08:35 +00002070// For register list parsing, we need to map from raw GPR register numbering
2071// to the enumeration values. The enumeration values aren't sorted by
2072// register number due to our using "sp", "lr" and "pc" as canonical names.
2073static unsigned getNextRegister(unsigned Reg) {
2074 // If this is a GPR, we need to do it manually, otherwise we can rely
2075 // on the sort ordering of the enumeration since the other reg-classes
2076 // are sane.
2077 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2078 return Reg + 1;
2079 switch(Reg) {
2080 default: assert(0 && "Invalid GPR number!");
2081 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2082 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2083 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2084 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2085 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2086 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2087 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2088 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2089 }
2090}
2091
2092/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002093bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002094parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002095 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002096 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002097 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002098 Parser.Lex(); // Eat '{' token.
2099 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002100
Jim Grosbachd0588e22011-09-14 18:08:35 +00002101 // Check the first register in the list to see what register class
2102 // this is a list of.
2103 int Reg = tryParseRegister();
2104 if (Reg == -1)
2105 return Error(RegLoc, "register expected");
2106
2107 MCRegisterClass *RC;
2108 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2109 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2110 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2111 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2112 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2113 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2114 else
2115 return Error(RegLoc, "invalid register in register list");
2116
2117 // The reglist instructions have at most 16 registers, so reserve
2118 // space for that many.
Jim Grosbachd7a2b3b2011-09-13 20:35:57 +00002119 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002120 // Store the first register.
2121 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002122
Jim Grosbachd0588e22011-09-14 18:08:35 +00002123 // This starts immediately after the first register token in the list,
2124 // so we can see either a comma or a minus (range separator) as a legal
2125 // next token.
2126 while (Parser.getTok().is(AsmToken::Comma) ||
2127 Parser.getTok().is(AsmToken::Minus)) {
2128 if (Parser.getTok().is(AsmToken::Minus)) {
2129 Parser.Lex(); // Eat the comma.
2130 SMLoc EndLoc = Parser.getTok().getLoc();
2131 int EndReg = tryParseRegister();
2132 if (EndReg == -1)
2133 return Error(EndLoc, "register expected");
2134 // If the register is the same as the start reg, there's nothing
2135 // more to do.
2136 if (Reg == EndReg)
2137 continue;
2138 // The register must be in the same register class as the first.
2139 if (!RC->contains(EndReg))
2140 return Error(EndLoc, "invalid register in register list");
2141 // Ranges must go from low to high.
2142 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2143 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002144
Jim Grosbachd0588e22011-09-14 18:08:35 +00002145 // Add all the registers in the range to the register list.
2146 while (Reg != EndReg) {
2147 Reg = getNextRegister(Reg);
2148 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2149 }
2150 continue;
2151 }
2152 Parser.Lex(); // Eat the comma.
2153 RegLoc = Parser.getTok().getLoc();
2154 int OldReg = Reg;
2155 Reg = tryParseRegister();
2156 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002157 return Error(RegLoc, "register expected");
Jim Grosbachd0588e22011-09-14 18:08:35 +00002158 // The register must be in the same register class as the first.
2159 if (!RC->contains(Reg))
2160 return Error(RegLoc, "invalid register in register list");
2161 // List must be monotonically increasing.
2162 if (getARMRegisterNumbering(Reg) <= getARMRegisterNumbering(OldReg))
2163 return Error(RegLoc, "register list not in ascending order");
2164 // VFP register lists must also be contiguous.
2165 // It's OK to use the enumeration values directly here rather, as the
2166 // VFP register classes have the enum sorted properly.
2167 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2168 Reg != OldReg + 1)
2169 return Error(RegLoc, "non-contiguous register range");
2170 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002171 }
2172
Jim Grosbachd0588e22011-09-14 18:08:35 +00002173 SMLoc E = Parser.getTok().getLoc();
2174 if (Parser.getTok().isNot(AsmToken::RCurly))
2175 return Error(E, "'}' expected");
2176 Parser.Lex(); // Eat '}' token.
2177
Bill Wendling50d0f582010-11-18 23:43:05 +00002178 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2179 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002180}
2181
Jim Grosbach43904292011-07-25 20:14:50 +00002182/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00002183ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002184parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002185 SMLoc S = Parser.getTok().getLoc();
2186 const AsmToken &Tok = Parser.getTok();
2187 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2188 StringRef OptStr = Tok.getString();
2189
2190 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2191 .Case("sy", ARM_MB::SY)
2192 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002193 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002194 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002195 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002196 .Case("ishst", ARM_MB::ISHST)
2197 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002198 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002199 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002200 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002201 .Case("osh", ARM_MB::OSH)
2202 .Case("oshst", ARM_MB::OSHST)
2203 .Default(~0U);
2204
2205 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00002206 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002207
2208 Parser.Lex(); // Eat identifier token.
2209 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002210 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002211}
2212
Jim Grosbach43904292011-07-25 20:14:50 +00002213/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002214ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002215parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002216 SMLoc S = Parser.getTok().getLoc();
2217 const AsmToken &Tok = Parser.getTok();
2218 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2219 StringRef IFlagsStr = Tok.getString();
2220
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002221 // An iflags string of "none" is interpreted to mean that none of the AIF
2222 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002223 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002224 if (IFlagsStr != "none") {
2225 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2226 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2227 .Case("a", ARM_PROC::A)
2228 .Case("i", ARM_PROC::I)
2229 .Case("f", ARM_PROC::F)
2230 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002231
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002232 // If some specific iflag is already set, it means that some letter is
2233 // present more than once, this is not acceptable.
2234 if (Flag == ~0U || (IFlags & Flag))
2235 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002236
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002237 IFlags |= Flag;
2238 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002239 }
2240
2241 Parser.Lex(); // Eat identifier token.
2242 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2243 return MatchOperand_Success;
2244}
2245
Jim Grosbach43904292011-07-25 20:14:50 +00002246/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002247ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002248parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002249 SMLoc S = Parser.getTok().getLoc();
2250 const AsmToken &Tok = Parser.getTok();
2251 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2252 StringRef Mask = Tok.getString();
2253
James Molloyacad68d2011-09-28 14:21:38 +00002254 if (isMClass()) {
2255 // See ARMv6-M 10.1.1
2256 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2257 .Case("apsr", 0)
2258 .Case("iapsr", 1)
2259 .Case("eapsr", 2)
2260 .Case("xpsr", 3)
2261 .Case("ipsr", 5)
2262 .Case("epsr", 6)
2263 .Case("iepsr", 7)
2264 .Case("msp", 8)
2265 .Case("psp", 9)
2266 .Case("primask", 16)
2267 .Case("basepri", 17)
2268 .Case("basepri_max", 18)
2269 .Case("faultmask", 19)
2270 .Case("control", 20)
2271 .Default(~0U);
2272
2273 if (FlagsVal == ~0U)
2274 return MatchOperand_NoMatch;
2275
2276 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
2277 // basepri, basepri_max and faultmask only valid for V7m.
2278 return MatchOperand_NoMatch;
2279
2280 Parser.Lex(); // Eat identifier token.
2281 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2282 return MatchOperand_Success;
2283 }
2284
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002285 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
2286 size_t Start = 0, Next = Mask.find('_');
2287 StringRef Flags = "";
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002288 std::string SpecReg = LowercaseString(Mask.slice(Start, Next));
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002289 if (Next != StringRef::npos)
2290 Flags = Mask.slice(Next+1, Mask.size());
2291
2292 // FlagsVal contains the complete mask:
2293 // 3-0: Mask
2294 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2295 unsigned FlagsVal = 0;
2296
2297 if (SpecReg == "apsr") {
2298 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002299 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002300 .Case("g", 0x4) // same as CPSR_s
2301 .Case("nzcvqg", 0xc) // same as CPSR_fs
2302 .Default(~0U);
2303
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002304 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002305 if (!Flags.empty())
2306 return MatchOperand_NoMatch;
2307 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00002308 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002309 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002310 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00002311 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
2312 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002313 for (int i = 0, e = Flags.size(); i != e; ++i) {
2314 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
2315 .Case("c", 1)
2316 .Case("x", 2)
2317 .Case("s", 4)
2318 .Case("f", 8)
2319 .Default(~0U);
2320
2321 // If some specific flag is already set, it means that some letter is
2322 // present more than once, this is not acceptable.
2323 if (FlagsVal == ~0U || (FlagsVal & Flag))
2324 return MatchOperand_NoMatch;
2325 FlagsVal |= Flag;
2326 }
2327 } else // No match for special register.
2328 return MatchOperand_NoMatch;
2329
2330 // Special register without flags are equivalent to "fc" flags.
2331 if (!FlagsVal)
2332 FlagsVal = 0x9;
2333
2334 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2335 if (SpecReg == "spsr")
2336 FlagsVal |= 16;
2337
2338 Parser.Lex(); // Eat identifier token.
2339 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2340 return MatchOperand_Success;
2341}
2342
Jim Grosbachf6c05252011-07-21 17:23:04 +00002343ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2344parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
2345 int Low, int High) {
2346 const AsmToken &Tok = Parser.getTok();
2347 if (Tok.isNot(AsmToken::Identifier)) {
2348 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2349 return MatchOperand_ParseFail;
2350 }
2351 StringRef ShiftName = Tok.getString();
2352 std::string LowerOp = LowercaseString(Op);
2353 std::string UpperOp = UppercaseString(Op);
2354 if (ShiftName != LowerOp && ShiftName != UpperOp) {
2355 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2356 return MatchOperand_ParseFail;
2357 }
2358 Parser.Lex(); // Eat shift type token.
2359
2360 // There must be a '#' and a shift amount.
2361 if (Parser.getTok().isNot(AsmToken::Hash)) {
2362 Error(Parser.getTok().getLoc(), "'#' expected");
2363 return MatchOperand_ParseFail;
2364 }
2365 Parser.Lex(); // Eat hash token.
2366
2367 const MCExpr *ShiftAmount;
2368 SMLoc Loc = Parser.getTok().getLoc();
2369 if (getParser().ParseExpression(ShiftAmount)) {
2370 Error(Loc, "illegal expression");
2371 return MatchOperand_ParseFail;
2372 }
2373 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2374 if (!CE) {
2375 Error(Loc, "constant expression expected");
2376 return MatchOperand_ParseFail;
2377 }
2378 int Val = CE->getValue();
2379 if (Val < Low || Val > High) {
2380 Error(Loc, "immediate value out of range");
2381 return MatchOperand_ParseFail;
2382 }
2383
2384 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
2385
2386 return MatchOperand_Success;
2387}
2388
Jim Grosbachc27d4f92011-07-22 17:44:50 +00002389ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2390parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2391 const AsmToken &Tok = Parser.getTok();
2392 SMLoc S = Tok.getLoc();
2393 if (Tok.isNot(AsmToken::Identifier)) {
2394 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2395 return MatchOperand_ParseFail;
2396 }
2397 int Val = StringSwitch<int>(Tok.getString())
2398 .Case("be", 1)
2399 .Case("le", 0)
2400 .Default(-1);
2401 Parser.Lex(); // Eat the token.
2402
2403 if (Val == -1) {
2404 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2405 return MatchOperand_ParseFail;
2406 }
2407 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
2408 getContext()),
2409 S, Parser.getTok().getLoc()));
2410 return MatchOperand_Success;
2411}
2412
Jim Grosbach580f4a92011-07-25 22:20:28 +00002413/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
2414/// instructions. Legal values are:
2415/// lsl #n 'n' in [0,31]
2416/// asr #n 'n' in [1,32]
2417/// n == 32 encoded as n == 0.
2418ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2419parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2420 const AsmToken &Tok = Parser.getTok();
2421 SMLoc S = Tok.getLoc();
2422 if (Tok.isNot(AsmToken::Identifier)) {
2423 Error(S, "shift operator 'asr' or 'lsl' expected");
2424 return MatchOperand_ParseFail;
2425 }
2426 StringRef ShiftName = Tok.getString();
2427 bool isASR;
2428 if (ShiftName == "lsl" || ShiftName == "LSL")
2429 isASR = false;
2430 else if (ShiftName == "asr" || ShiftName == "ASR")
2431 isASR = true;
2432 else {
2433 Error(S, "shift operator 'asr' or 'lsl' expected");
2434 return MatchOperand_ParseFail;
2435 }
2436 Parser.Lex(); // Eat the operator.
2437
2438 // A '#' and a shift amount.
2439 if (Parser.getTok().isNot(AsmToken::Hash)) {
2440 Error(Parser.getTok().getLoc(), "'#' expected");
2441 return MatchOperand_ParseFail;
2442 }
2443 Parser.Lex(); // Eat hash token.
2444
2445 const MCExpr *ShiftAmount;
2446 SMLoc E = Parser.getTok().getLoc();
2447 if (getParser().ParseExpression(ShiftAmount)) {
2448 Error(E, "malformed shift expression");
2449 return MatchOperand_ParseFail;
2450 }
2451 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2452 if (!CE) {
2453 Error(E, "shift amount must be an immediate");
2454 return MatchOperand_ParseFail;
2455 }
2456
2457 int64_t Val = CE->getValue();
2458 if (isASR) {
2459 // Shift amount must be in [1,32]
2460 if (Val < 1 || Val > 32) {
2461 Error(E, "'asr' shift amount must be in range [1,32]");
2462 return MatchOperand_ParseFail;
2463 }
Owen Anderson0afa0092011-09-26 21:06:22 +00002464 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
2465 if (isThumb() && Val == 32) {
2466 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
2467 return MatchOperand_ParseFail;
2468 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00002469 if (Val == 32) Val = 0;
2470 } else {
2471 // Shift amount must be in [1,32]
2472 if (Val < 0 || Val > 31) {
2473 Error(E, "'lsr' shift amount must be in range [0,31]");
2474 return MatchOperand_ParseFail;
2475 }
2476 }
2477
2478 E = Parser.getTok().getLoc();
2479 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
2480
2481 return MatchOperand_Success;
2482}
2483
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002484/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
2485/// of instructions. Legal values are:
2486/// ror #n 'n' in {0, 8, 16, 24}
2487ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2488parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2489 const AsmToken &Tok = Parser.getTok();
2490 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00002491 if (Tok.isNot(AsmToken::Identifier))
2492 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002493 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00002494 if (ShiftName != "ror" && ShiftName != "ROR")
2495 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002496 Parser.Lex(); // Eat the operator.
2497
2498 // A '#' and a rotate amount.
2499 if (Parser.getTok().isNot(AsmToken::Hash)) {
2500 Error(Parser.getTok().getLoc(), "'#' expected");
2501 return MatchOperand_ParseFail;
2502 }
2503 Parser.Lex(); // Eat hash token.
2504
2505 const MCExpr *ShiftAmount;
2506 SMLoc E = Parser.getTok().getLoc();
2507 if (getParser().ParseExpression(ShiftAmount)) {
2508 Error(E, "malformed rotate expression");
2509 return MatchOperand_ParseFail;
2510 }
2511 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2512 if (!CE) {
2513 Error(E, "rotate amount must be an immediate");
2514 return MatchOperand_ParseFail;
2515 }
2516
2517 int64_t Val = CE->getValue();
2518 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
2519 // normally, zero is represented in asm by omitting the rotate operand
2520 // entirely.
2521 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
2522 Error(E, "'ror' rotate amount must be 8, 16, or 24");
2523 return MatchOperand_ParseFail;
2524 }
2525
2526 E = Parser.getTok().getLoc();
2527 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
2528
2529 return MatchOperand_Success;
2530}
2531
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002532ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2533parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2534 SMLoc S = Parser.getTok().getLoc();
2535 // The bitfield descriptor is really two operands, the LSB and the width.
2536 if (Parser.getTok().isNot(AsmToken::Hash)) {
2537 Error(Parser.getTok().getLoc(), "'#' expected");
2538 return MatchOperand_ParseFail;
2539 }
2540 Parser.Lex(); // Eat hash token.
2541
2542 const MCExpr *LSBExpr;
2543 SMLoc E = Parser.getTok().getLoc();
2544 if (getParser().ParseExpression(LSBExpr)) {
2545 Error(E, "malformed immediate expression");
2546 return MatchOperand_ParseFail;
2547 }
2548 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
2549 if (!CE) {
2550 Error(E, "'lsb' operand must be an immediate");
2551 return MatchOperand_ParseFail;
2552 }
2553
2554 int64_t LSB = CE->getValue();
2555 // The LSB must be in the range [0,31]
2556 if (LSB < 0 || LSB > 31) {
2557 Error(E, "'lsb' operand must be in the range [0,31]");
2558 return MatchOperand_ParseFail;
2559 }
2560 E = Parser.getTok().getLoc();
2561
2562 // Expect another immediate operand.
2563 if (Parser.getTok().isNot(AsmToken::Comma)) {
2564 Error(Parser.getTok().getLoc(), "too few operands");
2565 return MatchOperand_ParseFail;
2566 }
2567 Parser.Lex(); // Eat hash token.
2568 if (Parser.getTok().isNot(AsmToken::Hash)) {
2569 Error(Parser.getTok().getLoc(), "'#' expected");
2570 return MatchOperand_ParseFail;
2571 }
2572 Parser.Lex(); // Eat hash token.
2573
2574 const MCExpr *WidthExpr;
2575 if (getParser().ParseExpression(WidthExpr)) {
2576 Error(E, "malformed immediate expression");
2577 return MatchOperand_ParseFail;
2578 }
2579 CE = dyn_cast<MCConstantExpr>(WidthExpr);
2580 if (!CE) {
2581 Error(E, "'width' operand must be an immediate");
2582 return MatchOperand_ParseFail;
2583 }
2584
2585 int64_t Width = CE->getValue();
2586 // The LSB must be in the range [1,32-lsb]
2587 if (Width < 1 || Width > 32 - LSB) {
2588 Error(E, "'width' operand must be in the range [1,32-lsb]");
2589 return MatchOperand_ParseFail;
2590 }
2591 E = Parser.getTok().getLoc();
2592
2593 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
2594
2595 return MatchOperand_Success;
2596}
2597
Jim Grosbach7ce05792011-08-03 23:50:40 +00002598ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2599parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2600 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002601 // postidx_reg := '+' register {, shift}
2602 // | '-' register {, shift}
2603 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00002604
2605 // This method must return MatchOperand_NoMatch without consuming any tokens
2606 // in the case where there is no match, as other alternatives take other
2607 // parse methods.
2608 AsmToken Tok = Parser.getTok();
2609 SMLoc S = Tok.getLoc();
2610 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00002611 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002612 int Reg = -1;
2613 if (Tok.is(AsmToken::Plus)) {
2614 Parser.Lex(); // Eat the '+' token.
2615 haveEaten = true;
2616 } else if (Tok.is(AsmToken::Minus)) {
2617 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00002618 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002619 haveEaten = true;
2620 }
2621 if (Parser.getTok().is(AsmToken::Identifier))
2622 Reg = tryParseRegister();
2623 if (Reg == -1) {
2624 if (!haveEaten)
2625 return MatchOperand_NoMatch;
2626 Error(Parser.getTok().getLoc(), "register expected");
2627 return MatchOperand_ParseFail;
2628 }
2629 SMLoc E = Parser.getTok().getLoc();
2630
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002631 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
2632 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002633 if (Parser.getTok().is(AsmToken::Comma)) {
2634 Parser.Lex(); // Eat the ','.
2635 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
2636 return MatchOperand_ParseFail;
2637 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002638
2639 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
2640 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00002641
2642 return MatchOperand_Success;
2643}
2644
Jim Grosbach251bf252011-08-10 21:56:18 +00002645ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2646parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2647 // Check for a post-index addressing register operand. Specifically:
2648 // am3offset := '+' register
2649 // | '-' register
2650 // | register
2651 // | # imm
2652 // | # + imm
2653 // | # - imm
2654
2655 // This method must return MatchOperand_NoMatch without consuming any tokens
2656 // in the case where there is no match, as other alternatives take other
2657 // parse methods.
2658 AsmToken Tok = Parser.getTok();
2659 SMLoc S = Tok.getLoc();
2660
2661 // Do immediates first, as we always parse those if we have a '#'.
2662 if (Parser.getTok().is(AsmToken::Hash)) {
2663 Parser.Lex(); // Eat the '#'.
2664 // Explicitly look for a '-', as we need to encode negative zero
2665 // differently.
2666 bool isNegative = Parser.getTok().is(AsmToken::Minus);
2667 const MCExpr *Offset;
2668 if (getParser().ParseExpression(Offset))
2669 return MatchOperand_ParseFail;
2670 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
2671 if (!CE) {
2672 Error(S, "constant expression expected");
2673 return MatchOperand_ParseFail;
2674 }
2675 SMLoc E = Tok.getLoc();
2676 // Negative zero is encoded as the flag value INT32_MIN.
2677 int32_t Val = CE->getValue();
2678 if (isNegative && Val == 0)
2679 Val = INT32_MIN;
2680
2681 Operands.push_back(
2682 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
2683
2684 return MatchOperand_Success;
2685 }
2686
2687
2688 bool haveEaten = false;
2689 bool isAdd = true;
2690 int Reg = -1;
2691 if (Tok.is(AsmToken::Plus)) {
2692 Parser.Lex(); // Eat the '+' token.
2693 haveEaten = true;
2694 } else if (Tok.is(AsmToken::Minus)) {
2695 Parser.Lex(); // Eat the '-' token.
2696 isAdd = false;
2697 haveEaten = true;
2698 }
2699 if (Parser.getTok().is(AsmToken::Identifier))
2700 Reg = tryParseRegister();
2701 if (Reg == -1) {
2702 if (!haveEaten)
2703 return MatchOperand_NoMatch;
2704 Error(Parser.getTok().getLoc(), "register expected");
2705 return MatchOperand_ParseFail;
2706 }
2707 SMLoc E = Parser.getTok().getLoc();
2708
2709 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
2710 0, S, E));
2711
2712 return MatchOperand_Success;
2713}
2714
Jim Grosbacha77295d2011-09-08 22:07:06 +00002715/// cvtT2LdrdPre - Convert parsed operands to MCInst.
2716/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2717/// when they refer multiple MIOperands inside a single one.
2718bool ARMAsmParser::
2719cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
2720 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2721 // Rt, Rt2
2722 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2723 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2724 // Create a writeback register dummy placeholder.
2725 Inst.addOperand(MCOperand::CreateReg(0));
2726 // addr
2727 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
2728 // pred
2729 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2730 return true;
2731}
2732
2733/// cvtT2StrdPre - Convert parsed operands to MCInst.
2734/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2735/// when they refer multiple MIOperands inside a single one.
2736bool ARMAsmParser::
2737cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
2738 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2739 // Create a writeback register dummy placeholder.
2740 Inst.addOperand(MCOperand::CreateReg(0));
2741 // Rt, Rt2
2742 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2743 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2744 // addr
2745 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
2746 // pred
2747 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2748 return true;
2749}
2750
Jim Grosbacheeec0252011-09-08 00:39:19 +00002751/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
2752/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2753/// when they refer multiple MIOperands inside a single one.
2754bool ARMAsmParser::
2755cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
2756 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2757 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2758
2759 // Create a writeback register dummy placeholder.
2760 Inst.addOperand(MCOperand::CreateImm(0));
2761
2762 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
2763 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2764 return true;
2765}
2766
Jim Grosbachee2c2a42011-09-16 21:55:56 +00002767/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
2768/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2769/// when they refer multiple MIOperands inside a single one.
2770bool ARMAsmParser::
2771cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
2772 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2773 // Create a writeback register dummy placeholder.
2774 Inst.addOperand(MCOperand::CreateImm(0));
2775 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2776 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
2777 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2778 return true;
2779}
2780
Jim Grosbach1355cf12011-07-26 17:10:22 +00002781/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002782/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2783/// when they refer multiple MIOperands inside a single one.
2784bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002785cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002786 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2787 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2788
2789 // Create a writeback register dummy placeholder.
2790 Inst.addOperand(MCOperand::CreateImm(0));
2791
Jim Grosbach7ce05792011-08-03 23:50:40 +00002792 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002793 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2794 return true;
2795}
2796
Owen Anderson9ab0f252011-08-26 20:43:14 +00002797/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
2798/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2799/// when they refer multiple MIOperands inside a single one.
2800bool ARMAsmParser::
2801cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
2802 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2803 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2804
2805 // Create a writeback register dummy placeholder.
2806 Inst.addOperand(MCOperand::CreateImm(0));
2807
2808 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
2809 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2810 return true;
2811}
2812
2813
Jim Grosbach548340c2011-08-11 19:22:40 +00002814/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
2815/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2816/// when they refer multiple MIOperands inside a single one.
2817bool ARMAsmParser::
2818cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
2819 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2820 // Create a writeback register dummy placeholder.
2821 Inst.addOperand(MCOperand::CreateImm(0));
2822 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2823 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
2824 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2825 return true;
2826}
2827
Jim Grosbach1355cf12011-07-26 17:10:22 +00002828/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002829/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2830/// when they refer multiple MIOperands inside a single one.
2831bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002832cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002833 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2834 // Create a writeback register dummy placeholder.
2835 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00002836 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2837 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
2838 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002839 return true;
2840}
2841
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00002842/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
2843/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2844/// when they refer multiple MIOperands inside a single one.
2845bool ARMAsmParser::
2846cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
2847 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2848 // Create a writeback register dummy placeholder.
2849 Inst.addOperand(MCOperand::CreateImm(0));
2850 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2851 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
2852 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2853 return true;
2854}
2855
Jim Grosbach7ce05792011-08-03 23:50:40 +00002856/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
2857/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2858/// when they refer multiple MIOperands inside a single one.
2859bool ARMAsmParser::
2860cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
2861 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2862 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002863 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002864 // Create a writeback register dummy placeholder.
2865 Inst.addOperand(MCOperand::CreateImm(0));
2866 // addr
2867 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
2868 // offset
2869 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
2870 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002871 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2872 return true;
2873}
2874
Jim Grosbach7ce05792011-08-03 23:50:40 +00002875/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002876/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2877/// when they refer multiple MIOperands inside a single one.
2878bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00002879cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
2880 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2881 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00002882 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002883 // Create a writeback register dummy placeholder.
2884 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00002885 // addr
2886 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
2887 // offset
2888 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
2889 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002890 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2891 return true;
2892}
2893
Jim Grosbach7ce05792011-08-03 23:50:40 +00002894/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002895/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2896/// when they refer multiple MIOperands inside a single one.
2897bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00002898cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
2899 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002900 // Create a writeback register dummy placeholder.
2901 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00002902 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002903 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002904 // addr
2905 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
2906 // offset
2907 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
2908 // pred
2909 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2910 return true;
2911}
2912
2913/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
2914/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2915/// when they refer multiple MIOperands inside a single one.
2916bool ARMAsmParser::
2917cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
2918 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2919 // Create a writeback register dummy placeholder.
2920 Inst.addOperand(MCOperand::CreateImm(0));
2921 // Rt
2922 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2923 // addr
2924 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
2925 // offset
2926 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
2927 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002928 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2929 return true;
2930}
2931
Jim Grosbach2fd2b872011-08-10 20:29:19 +00002932/// cvtLdrdPre - Convert parsed operands to MCInst.
2933/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2934/// when they refer multiple MIOperands inside a single one.
2935bool ARMAsmParser::
2936cvtLdrdPre(MCInst &Inst, unsigned Opcode,
2937 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2938 // Rt, Rt2
2939 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2940 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2941 // Create a writeback register dummy placeholder.
2942 Inst.addOperand(MCOperand::CreateImm(0));
2943 // addr
2944 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
2945 // pred
2946 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2947 return true;
2948}
2949
Jim Grosbach14605d12011-08-11 20:28:23 +00002950/// cvtStrdPre - Convert parsed operands to MCInst.
2951/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2952/// when they refer multiple MIOperands inside a single one.
2953bool ARMAsmParser::
2954cvtStrdPre(MCInst &Inst, unsigned Opcode,
2955 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2956 // Create a writeback register dummy placeholder.
2957 Inst.addOperand(MCOperand::CreateImm(0));
2958 // Rt, Rt2
2959 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2960 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2961 // addr
2962 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
2963 // pred
2964 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2965 return true;
2966}
2967
Jim Grosbach623a4542011-08-10 22:42:16 +00002968/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
2969/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2970/// when they refer multiple MIOperands inside a single one.
2971bool ARMAsmParser::
2972cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
2973 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2974 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2975 // Create a writeback register dummy placeholder.
2976 Inst.addOperand(MCOperand::CreateImm(0));
2977 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
2978 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2979 return true;
2980}
2981
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00002982/// cvtThumbMultiple- Convert parsed operands to MCInst.
2983/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2984/// when they refer multiple MIOperands inside a single one.
2985bool ARMAsmParser::
2986cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
2987 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2988 // The second source operand must be the same register as the destination
2989 // operand.
2990 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00002991 (((ARMOperand*)Operands[3])->getReg() !=
2992 ((ARMOperand*)Operands[5])->getReg()) &&
2993 (((ARMOperand*)Operands[3])->getReg() !=
2994 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00002995 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00002996 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00002997 return false;
2998 }
2999 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3000 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
3001 ((ARMOperand*)Operands[4])->addRegOperands(Inst, 1);
Jim Grosbach7a010692011-08-19 22:30:46 +00003002 // If we have a three-operand form, use that, else the second source operand
3003 // is just the destination operand again.
3004 if (Operands.size() == 6)
3005 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3006 else
3007 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003008 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3009
3010 return true;
3011}
Jim Grosbach623a4542011-08-10 22:42:16 +00003012
Bill Wendlinge7176102010-11-06 22:36:58 +00003013/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003014/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00003015bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003016parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00003017 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00003018 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00003019 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00003020 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003021 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003022
Sean Callanan18b83232010-01-19 21:44:56 +00003023 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00003024 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00003025 if (BaseRegNum == -1)
3026 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003027
Daniel Dunbar05710932011-01-18 05:34:17 +00003028 // The next token must either be a comma or a closing bracket.
3029 const AsmToken &Tok = Parser.getTok();
3030 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003031 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00003032
Jim Grosbach7ce05792011-08-03 23:50:40 +00003033 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00003034 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003035 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003036
Jim Grosbach7ce05792011-08-03 23:50:40 +00003037 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003038 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00003039
Jim Grosbachfb12f352011-09-19 18:42:21 +00003040 // If there's a pre-indexing writeback marker, '!', just add it as a token
3041 // operand. It's rather odd, but syntactically valid.
3042 if (Parser.getTok().is(AsmToken::Exclaim)) {
3043 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3044 Parser.Lex(); // Eat the '!'.
3045 }
3046
Jim Grosbach7ce05792011-08-03 23:50:40 +00003047 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003048 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003049
Jim Grosbach7ce05792011-08-03 23:50:40 +00003050 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3051 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003052
Jim Grosbach57dcb852011-10-11 17:29:55 +00003053 // If we have a ':', it's an alignment specifier.
3054 if (Parser.getTok().is(AsmToken::Colon)) {
3055 Parser.Lex(); // Eat the ':'.
3056 E = Parser.getTok().getLoc();
3057
3058 const MCExpr *Expr;
3059 if (getParser().ParseExpression(Expr))
3060 return true;
3061
3062 // The expression has to be a constant. Memory references with relocations
3063 // don't come through here, as they use the <label> forms of the relevant
3064 // instructions.
3065 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3066 if (!CE)
3067 return Error (E, "constant expression expected");
3068
3069 unsigned Align = 0;
3070 switch (CE->getValue()) {
3071 default:
3072 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3073 case 64: Align = 8; break;
3074 case 128: Align = 16; break;
3075 case 256: Align = 32; break;
3076 }
3077
3078 // Now we should have the closing ']'
3079 E = Parser.getTok().getLoc();
3080 if (Parser.getTok().isNot(AsmToken::RBrac))
3081 return Error(E, "']' expected");
3082 Parser.Lex(); // Eat right bracket token.
3083
3084 // Don't worry about range checking the value here. That's handled by
3085 // the is*() predicates.
3086 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3087 ARM_AM::no_shift, 0, Align,
3088 false, S, E));
3089
3090 // If there's a pre-indexing writeback marker, '!', just add it as a token
3091 // operand.
3092 if (Parser.getTok().is(AsmToken::Exclaim)) {
3093 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3094 Parser.Lex(); // Eat the '!'.
3095 }
3096
3097 return false;
3098 }
3099
3100 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach7ce05792011-08-03 23:50:40 +00003101 // offset.
3102 if (Parser.getTok().is(AsmToken::Hash)) {
3103 Parser.Lex(); // Eat the '#'.
3104 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003105
Owen Anderson0da10cf2011-08-29 19:36:44 +00003106 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003107 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003108 if (getParser().ParseExpression(Offset))
3109 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003110
3111 // The expression has to be a constant. Memory references with relocations
3112 // don't come through here, as they use the <label> forms of the relevant
3113 // instructions.
3114 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3115 if (!CE)
3116 return Error (E, "constant expression expected");
3117
Owen Anderson0da10cf2011-08-29 19:36:44 +00003118 // If the constant was #-0, represent it as INT32_MIN.
3119 int32_t Val = CE->getValue();
3120 if (isNegative && Val == 0)
3121 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3122
Jim Grosbach7ce05792011-08-03 23:50:40 +00003123 // Now we should have the closing ']'
3124 E = Parser.getTok().getLoc();
3125 if (Parser.getTok().isNot(AsmToken::RBrac))
3126 return Error(E, "']' expected");
3127 Parser.Lex(); // Eat right bracket token.
3128
3129 // Don't worry about range checking the value here. That's handled by
3130 // the is*() predicates.
3131 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003132 ARM_AM::no_shift, 0, 0,
3133 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003134
3135 // If there's a pre-indexing writeback marker, '!', just add it as a token
3136 // operand.
3137 if (Parser.getTok().is(AsmToken::Exclaim)) {
3138 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3139 Parser.Lex(); // Eat the '!'.
3140 }
3141
3142 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003143 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003144
3145 // The register offset is optionally preceded by a '+' or '-'
3146 bool isNegative = false;
3147 if (Parser.getTok().is(AsmToken::Minus)) {
3148 isNegative = true;
3149 Parser.Lex(); // Eat the '-'.
3150 } else if (Parser.getTok().is(AsmToken::Plus)) {
3151 // Nothing to do.
3152 Parser.Lex(); // Eat the '+'.
3153 }
3154
3155 E = Parser.getTok().getLoc();
3156 int OffsetRegNum = tryParseRegister();
3157 if (OffsetRegNum == -1)
3158 return Error(E, "register expected");
3159
3160 // If there's a shift operator, handle it.
3161 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003162 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003163 if (Parser.getTok().is(AsmToken::Comma)) {
3164 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003165 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003166 return true;
3167 }
3168
3169 // Now we should have the closing ']'
3170 E = Parser.getTok().getLoc();
3171 if (Parser.getTok().isNot(AsmToken::RBrac))
3172 return Error(E, "']' expected");
3173 Parser.Lex(); // Eat right bracket token.
3174
3175 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003176 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00003177 S, E));
3178
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003179 // If there's a pre-indexing writeback marker, '!', just add it as a token
3180 // operand.
3181 if (Parser.getTok().is(AsmToken::Exclaim)) {
3182 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3183 Parser.Lex(); // Eat the '!'.
3184 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003185
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003186 return false;
3187}
3188
Jim Grosbach7ce05792011-08-03 23:50:40 +00003189/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003190/// ( lsl | lsr | asr | ror ) , # shift_amount
3191/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00003192/// return true if it parses a shift otherwise it returns false.
3193bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
3194 unsigned &Amount) {
3195 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00003196 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003197 if (Tok.isNot(AsmToken::Identifier))
3198 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00003199 StringRef ShiftName = Tok.getString();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003200 if (ShiftName == "lsl" || ShiftName == "LSL")
Owen Anderson00828302011-03-18 22:50:18 +00003201 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003202 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00003203 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003204 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00003205 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003206 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00003207 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003208 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00003209 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003210 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00003211 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00003212 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003213
Jim Grosbach7ce05792011-08-03 23:50:40 +00003214 // rrx stands alone.
3215 Amount = 0;
3216 if (St != ARM_AM::rrx) {
3217 Loc = Parser.getTok().getLoc();
3218 // A '#' and a shift amount.
3219 const AsmToken &HashTok = Parser.getTok();
3220 if (HashTok.isNot(AsmToken::Hash))
3221 return Error(HashTok.getLoc(), "'#' expected");
3222 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003223
Jim Grosbach7ce05792011-08-03 23:50:40 +00003224 const MCExpr *Expr;
3225 if (getParser().ParseExpression(Expr))
3226 return true;
3227 // Range check the immediate.
3228 // lsl, ror: 0 <= imm <= 31
3229 // lsr, asr: 0 <= imm <= 32
3230 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3231 if (!CE)
3232 return Error(Loc, "shift amount must be an immediate");
3233 int64_t Imm = CE->getValue();
3234 if (Imm < 0 ||
3235 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
3236 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
3237 return Error(Loc, "immediate shift value out of range");
3238 Amount = Imm;
3239 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003240
3241 return false;
3242}
3243
Jim Grosbach9d390362011-10-03 23:38:36 +00003244/// parseFPImm - A floating point immediate expression operand.
3245ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3246parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3247 SMLoc S = Parser.getTok().getLoc();
3248
3249 if (Parser.getTok().isNot(AsmToken::Hash))
3250 return MatchOperand_NoMatch;
3251 Parser.Lex(); // Eat the '#'.
3252
3253 // Handle negation, as that still comes through as a separate token.
3254 bool isNegative = false;
3255 if (Parser.getTok().is(AsmToken::Minus)) {
3256 isNegative = true;
3257 Parser.Lex();
3258 }
3259 const AsmToken &Tok = Parser.getTok();
3260 if (Tok.is(AsmToken::Real)) {
3261 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
3262 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3263 // If we had a '-' in front, toggle the sign bit.
3264 IntVal ^= (uint64_t)isNegative << 63;
3265 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
3266 Parser.Lex(); // Eat the token.
3267 if (Val == -1) {
3268 TokError("floating point value out of range");
3269 return MatchOperand_ParseFail;
3270 }
3271 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3272 return MatchOperand_Success;
3273 }
3274 if (Tok.is(AsmToken::Integer)) {
3275 int64_t Val = Tok.getIntVal();
3276 Parser.Lex(); // Eat the token.
3277 if (Val > 255 || Val < 0) {
3278 TokError("encoded floating point value out of range");
3279 return MatchOperand_ParseFail;
3280 }
3281 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3282 return MatchOperand_Success;
3283 }
3284
3285 TokError("invalid floating point immediate");
3286 return MatchOperand_ParseFail;
3287}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003288/// Parse a arm instruction operand. For now this parses the operand regardless
3289/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003290bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003291 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00003292 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003293
3294 // Check if the current operand has a custom associated parser, if so, try to
3295 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00003296 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3297 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003298 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00003299 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3300 // there was a match, but an error occurred, in which case, just return that
3301 // the operand parsing failed.
3302 if (ResTy == MatchOperand_ParseFail)
3303 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003304
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003305 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00003306 default:
3307 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00003308 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00003309 case AsmToken::Identifier: {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003310 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003311 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00003312 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00003313 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00003314 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00003315 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00003316 else if (Res == -1) // irrecoverable error
3317 return true;
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003318 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
3319 S = Parser.getTok().getLoc();
3320 Parser.Lex();
3321 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
3322 return false;
3323 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00003324
3325 // Fall though for the Identifier case that is not a register or a
3326 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00003327 }
Kevin Enderby67b212e2011-01-13 20:32:36 +00003328 case AsmToken::Integer: // things like 1f and 2b as a branch targets
3329 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00003330 // This was not a register so parse other operands that start with an
3331 // identifier (like labels) as expressions and create them as immediates.
3332 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00003333 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00003334 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003335 return true;
Sean Callanan76264762010-04-02 22:27:05 +00003336 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003337 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
3338 return false;
3339 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003340 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003341 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00003342 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003343 return parseRegisterList(Operands);
Owen Anderson63553c72011-08-29 17:17:09 +00003344 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00003345 // #42 -> immediate.
3346 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00003347 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003348 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00003349 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00003350 const MCExpr *ImmVal;
3351 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003352 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00003353 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
3354 if (!CE) {
3355 Error(S, "constant expression expected");
3356 return MatchOperand_ParseFail;
3357 }
3358 int32_t Val = CE->getValue();
3359 if (isNegative && Val == 0)
3360 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Sean Callanan76264762010-04-02 22:27:05 +00003361 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003362 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
3363 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00003364 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003365 case AsmToken::Colon: {
3366 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00003367 // FIXME: Check it's an expression prefix,
3368 // e.g. (FOO - :lower16:BAR) isn't legal.
3369 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003370 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003371 return true;
3372
Evan Cheng75972122011-01-13 07:58:56 +00003373 const MCExpr *SubExprVal;
3374 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003375 return true;
3376
Evan Cheng75972122011-01-13 07:58:56 +00003377 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
3378 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00003379 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00003380 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00003381 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003382 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003383 }
3384}
3385
Jim Grosbach1355cf12011-07-26 17:10:22 +00003386// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00003387// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003388bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00003389 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003390
3391 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00003392 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00003393 Parser.Lex(); // Eat ':'
3394
3395 if (getLexer().isNot(AsmToken::Identifier)) {
3396 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
3397 return true;
3398 }
3399
3400 StringRef IDVal = Parser.getTok().getIdentifier();
3401 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00003402 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003403 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00003404 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003405 } else {
3406 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
3407 return true;
3408 }
3409 Parser.Lex();
3410
3411 if (getLexer().isNot(AsmToken::Colon)) {
3412 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
3413 return true;
3414 }
3415 Parser.Lex(); // Eat the last ':'
3416 return false;
3417}
3418
Daniel Dunbar352e1482011-01-11 15:59:50 +00003419/// \brief Given a mnemonic, split out possible predication code and carry
3420/// setting letters to form a canonical mnemonic and flags.
3421//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003422// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00003423// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003424StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00003425 unsigned &PredicationCode,
3426 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00003427 unsigned &ProcessorIMod,
3428 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003429 PredicationCode = ARMCC::AL;
3430 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003431 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00003432
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003433 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00003434 //
3435 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00003436 if ((Mnemonic == "movs" && isThumb()) ||
3437 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
3438 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
3439 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
3440 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
3441 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
3442 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
3443 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar352e1482011-01-11 15:59:50 +00003444 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00003445
Jim Grosbach3f00e312011-07-11 17:09:57 +00003446 // First, split out any predication code. Ignore mnemonics we know aren't
3447 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00003448 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00003449 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00003450 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00003451 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00003452 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
3453 .Case("eq", ARMCC::EQ)
3454 .Case("ne", ARMCC::NE)
3455 .Case("hs", ARMCC::HS)
3456 .Case("cs", ARMCC::HS)
3457 .Case("lo", ARMCC::LO)
3458 .Case("cc", ARMCC::LO)
3459 .Case("mi", ARMCC::MI)
3460 .Case("pl", ARMCC::PL)
3461 .Case("vs", ARMCC::VS)
3462 .Case("vc", ARMCC::VC)
3463 .Case("hi", ARMCC::HI)
3464 .Case("ls", ARMCC::LS)
3465 .Case("ge", ARMCC::GE)
3466 .Case("lt", ARMCC::LT)
3467 .Case("gt", ARMCC::GT)
3468 .Case("le", ARMCC::LE)
3469 .Case("al", ARMCC::AL)
3470 .Default(~0U);
3471 if (CC != ~0U) {
3472 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
3473 PredicationCode = CC;
3474 }
Bill Wendling52925b62010-10-29 23:50:21 +00003475 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003476
Daniel Dunbar352e1482011-01-11 15:59:50 +00003477 // Next, determine if we have a carry setting bit. We explicitly ignore all
3478 // the instructions we know end in 's'.
3479 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00003480 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00003481 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
3482 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
3483 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00003484 Mnemonic == "vrsqrts" || Mnemonic == "srs" ||
3485 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003486 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
3487 CarrySetting = true;
3488 }
3489
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003490 // The "cps" instruction can have a interrupt mode operand which is glued into
3491 // the mnemonic. Check if this is the case, split it and parse the imod op
3492 if (Mnemonic.startswith("cps")) {
3493 // Split out any imod code.
3494 unsigned IMod =
3495 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
3496 .Case("ie", ARM_PROC::IE)
3497 .Case("id", ARM_PROC::ID)
3498 .Default(~0U);
3499 if (IMod != ~0U) {
3500 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
3501 ProcessorIMod = IMod;
3502 }
3503 }
3504
Jim Grosbach89df9962011-08-26 21:43:41 +00003505 // The "it" instruction has the condition mask on the end of the mnemonic.
3506 if (Mnemonic.startswith("it")) {
3507 ITMask = Mnemonic.slice(2, Mnemonic.size());
3508 Mnemonic = Mnemonic.slice(0, 2);
3509 }
3510
Daniel Dunbar352e1482011-01-11 15:59:50 +00003511 return Mnemonic;
3512}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003513
3514/// \brief Given a canonical mnemonic, determine if the instruction ever allows
3515/// inclusion of carry set or predication code operands.
3516//
3517// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00003518void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003519getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00003520 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003521 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
3522 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00003523 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003524 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003525 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003526 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003527 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00003528 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003529 Mnemonic == "mla" || Mnemonic == "smlal" ||
3530 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003531 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003532 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003533 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003534
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003535 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
3536 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
3537 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
3538 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00003539 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
3540 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00003541 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00003542 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw") &&
3543 !isThumb()) ||
3544 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
3545 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00003546 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003547 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003548 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003549 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003550
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003551 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003552 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00003553 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003554 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003555 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003556}
3557
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003558bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
3559 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003560 // FIXME: This is all horribly hacky. We really need a better way to deal
3561 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003562
3563 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
3564 // another does not. Specifically, the MOVW instruction does not. So we
3565 // special case it here and remove the defaulted (non-setting) cc_out
3566 // operand if that's the instruction we're trying to match.
3567 //
3568 // We do this as post-processing of the explicit operands rather than just
3569 // conditionally adding the cc_out in the first place because we need
3570 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00003571 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003572 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
3573 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
3574 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3575 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00003576
3577 // Register-register 'add' for thumb does not have a cc_out operand
3578 // when there are only two register operands.
3579 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
3580 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3581 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3582 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3583 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00003584 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003585 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
3586 // have to check the immediate range here since Thumb2 has a variant
3587 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00003588 if (((isThumb() && Mnemonic == "add") ||
3589 (isThumbTwo() && Mnemonic == "sub")) &&
3590 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00003591 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3592 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3593 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003594 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
3595 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
3596 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00003597 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00003598 // For Thumb2, add/sub immediate does not have a cc_out operand for the
3599 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003600 // selecting via the generic "add" mnemonic, so to know that we
3601 // should remove the cc_out operand, we have to explicitly check that
3602 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00003603 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
3604 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003605 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3606 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3607 static_cast<ARMOperand*>(Operands[5])->isImm()) {
3608 // Nest conditions rather than one big 'if' statement for readability.
3609 //
3610 // If either register is a high reg, it's either one of the SP
3611 // variants (handled above) or a 32-bit encoding, so we just
3612 // check against T3.
3613 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
3614 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
3615 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
3616 return false;
3617 // If both registers are low, we're in an IT block, and the immediate is
3618 // in range, we should use encoding T1 instead, which has a cc_out.
3619 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00003620 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003621 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
3622 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
3623 return false;
3624
3625 // Otherwise, we use encoding T4, which does not have a cc_out
3626 // operand.
3627 return true;
3628 }
3629
Jim Grosbach64944f42011-09-14 21:00:40 +00003630 // The thumb2 multiply instruction doesn't have a CCOut register, so
3631 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
3632 // use the 16-bit encoding or not.
3633 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
3634 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
3635 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3636 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3637 static_cast<ARMOperand*>(Operands[5])->isReg() &&
3638 // If the registers aren't low regs, the destination reg isn't the
3639 // same as one of the source regs, or the cc_out operand is zero
3640 // outside of an IT block, we have to use the 32-bit encoding, so
3641 // remove the cc_out operand.
3642 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
3643 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
3644 !inITBlock() ||
3645 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
3646 static_cast<ARMOperand*>(Operands[5])->getReg() &&
3647 static_cast<ARMOperand*>(Operands[3])->getReg() !=
3648 static_cast<ARMOperand*>(Operands[4])->getReg())))
3649 return true;
3650
3651
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003652
Jim Grosbachf69c8042011-08-24 21:42:27 +00003653 // Register-register 'add/sub' for thumb does not have a cc_out operand
3654 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
3655 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
3656 // right, this will result in better diagnostics (which operand is off)
3657 // anyway.
3658 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
3659 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00003660 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3661 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
3662 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3663 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00003664
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003665 return false;
3666}
3667
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003668/// Parse an arm instruction mnemonic followed by its operands.
3669bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
3670 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3671 // Create the leading tokens for the mnemonic, split by '.' characters.
3672 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00003673 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003674
Daniel Dunbar352e1482011-01-11 15:59:50 +00003675 // Split out the predication code and carry setting flag from the mnemonic.
3676 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003677 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00003678 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00003679 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003680 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00003681 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003682
Jim Grosbach0c49ac02011-08-25 17:23:55 +00003683 // In Thumb1, only the branch (B) instruction can be predicated.
3684 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
3685 Parser.EatToEndOfStatement();
3686 return Error(NameLoc, "conditional execution not supported in Thumb1");
3687 }
3688
Jim Grosbachffa32252011-07-19 19:13:28 +00003689 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
3690
Jim Grosbach89df9962011-08-26 21:43:41 +00003691 // Handle the IT instruction ITMask. Convert it to a bitmask. This
3692 // is the mask as it will be for the IT encoding if the conditional
3693 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
3694 // where the conditional bit0 is zero, the instruction post-processing
3695 // will adjust the mask accordingly.
3696 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003697 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
3698 if (ITMask.size() > 3) {
3699 Parser.EatToEndOfStatement();
3700 return Error(Loc, "too many conditions on IT instruction");
3701 }
Jim Grosbach89df9962011-08-26 21:43:41 +00003702 unsigned Mask = 8;
3703 for (unsigned i = ITMask.size(); i != 0; --i) {
3704 char pos = ITMask[i - 1];
3705 if (pos != 't' && pos != 'e') {
3706 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003707 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00003708 }
3709 Mask >>= 1;
3710 if (ITMask[i - 1] == 't')
3711 Mask |= 8;
3712 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003713 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00003714 }
3715
Jim Grosbachffa32252011-07-19 19:13:28 +00003716 // FIXME: This is all a pretty gross hack. We should automatically handle
3717 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00003718
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003719 // Next, add the CCOut and ConditionCode operands, if needed.
3720 //
3721 // For mnemonics which can ever incorporate a carry setting bit or predication
3722 // code, our matching model involves us always generating CCOut and
3723 // ConditionCode operands to match the mnemonic "as written" and then we let
3724 // the matcher deal with finding the right instruction or generating an
3725 // appropriate error.
3726 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003727 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003728
Jim Grosbach33c16a22011-07-14 22:04:21 +00003729 // If we had a carry-set on an instruction that can't do that, issue an
3730 // error.
3731 if (!CanAcceptCarrySet && CarrySetting) {
3732 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00003733 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00003734 "' can not set flags, but 's' suffix specified");
3735 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003736 // If we had a predication code on an instruction that can't do that, issue an
3737 // error.
3738 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
3739 Parser.EatToEndOfStatement();
3740 return Error(NameLoc, "instruction '" + Mnemonic +
3741 "' is not predicable, but condition code specified");
3742 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00003743
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003744 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003745 if (CanAcceptCarrySet) {
3746 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003747 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003748 Loc));
3749 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003750
3751 // Add the predication code operand, if necessary.
3752 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003753 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
3754 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003755 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003756 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003757 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003758
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003759 // Add the processor imod operand, if necessary.
3760 if (ProcessorIMod) {
3761 Operands.push_back(ARMOperand::CreateImm(
3762 MCConstantExpr::Create(ProcessorIMod, getContext()),
3763 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003764 }
3765
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003766 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00003767 while (Next != StringRef::npos) {
3768 Start = Next;
3769 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003770 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003771
Jim Grosbach4d23e992011-08-24 22:19:48 +00003772 // For now, we're only parsing Thumb1 (for the most part), so
3773 // just ignore ".n" qualifiers. We'll use them to restrict
3774 // matching when we do Thumb2.
Jim Grosbach81d2e392011-09-07 16:06:04 +00003775 if (ExtraToken != ".n") {
3776 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
3777 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
3778 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00003779 }
3780
3781 // Read the remaining operands.
3782 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003783 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003784 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00003785 Parser.EatToEndOfStatement();
3786 return true;
3787 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003788
3789 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00003790 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003791
3792 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003793 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00003794 Parser.EatToEndOfStatement();
3795 return true;
3796 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003797 }
3798 }
Jim Grosbach16c74252010-10-29 14:46:02 +00003799
Chris Lattnercbf8a982010-09-11 16:18:25 +00003800 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00003801 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00003802 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00003803 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00003804 }
Bill Wendling146018f2010-11-06 21:42:12 +00003805
Chris Lattner34e53142010-09-08 05:10:46 +00003806 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00003807
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003808 // Some instructions, mostly Thumb, have forms for the same mnemonic that
3809 // do and don't have a cc_out optional-def operand. With some spot-checks
3810 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003811 // parse and adjust accordingly before actually matching. We shouldn't ever
3812 // try to remove a cc_out operand that was explicitly set on the the
3813 // mnemonic, of course (CarrySetting == true). Reason number #317 the
3814 // table driven matcher doesn't fit well with the ARM instruction set.
3815 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00003816 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
3817 Operands.erase(Operands.begin() + 1);
3818 delete Op;
3819 }
3820
Jim Grosbachcf121c32011-07-28 21:57:55 +00003821 // ARM mode 'blx' need special handling, as the register operand version
3822 // is predicable, but the label operand version is not. So, we can't rely
3823 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00003824 // a k_CondCode operand in the list. If we're trying to match the label
3825 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00003826 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
3827 static_cast<ARMOperand*>(Operands[2])->isImm()) {
3828 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
3829 Operands.erase(Operands.begin() + 1);
3830 delete Op;
3831 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00003832
3833 // The vector-compare-to-zero instructions have a literal token "#0" at
3834 // the end that comes to here as an immediate operand. Convert it to a
3835 // token to play nicely with the matcher.
3836 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
3837 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
3838 static_cast<ARMOperand*>(Operands[5])->isImm()) {
3839 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
3840 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
3841 if (CE && CE->getValue() == 0) {
3842 Operands.erase(Operands.begin() + 5);
3843 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
3844 delete Op;
3845 }
3846 }
Jim Grosbach68259142011-10-03 22:30:24 +00003847 // VCMP{E} does the same thing, but with a different operand count.
3848 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
3849 static_cast<ARMOperand*>(Operands[4])->isImm()) {
3850 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
3851 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
3852 if (CE && CE->getValue() == 0) {
3853 Operands.erase(Operands.begin() + 4);
3854 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
3855 delete Op;
3856 }
3857 }
Jim Grosbach934755a2011-08-22 23:47:13 +00003858 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
3859 // end. Convert it to a token here.
3860 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
3861 static_cast<ARMOperand*>(Operands[5])->isImm()) {
3862 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
3863 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
3864 if (CE && CE->getValue() == 0) {
3865 Operands.erase(Operands.begin() + 5);
3866 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
3867 delete Op;
3868 }
3869 }
3870
Chris Lattner98986712010-01-14 22:21:20 +00003871 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00003872}
3873
Jim Grosbach189610f2011-07-26 18:25:39 +00003874// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00003875
3876// return 'true' if register list contains non-low GPR registers,
3877// 'false' otherwise. If Reg is in the register list or is HiReg, set
3878// 'containsReg' to true.
3879static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
3880 unsigned HiReg, bool &containsReg) {
3881 containsReg = false;
3882 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
3883 unsigned OpReg = Inst.getOperand(i).getReg();
3884 if (OpReg == Reg)
3885 containsReg = true;
3886 // Anything other than a low register isn't legal here.
3887 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
3888 return true;
3889 }
3890 return false;
3891}
3892
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00003893// Check if the specified regisgter is in the register list of the inst,
3894// starting at the indicated operand number.
3895static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
3896 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
3897 unsigned OpReg = Inst.getOperand(i).getReg();
3898 if (OpReg == Reg)
3899 return true;
3900 }
3901 return false;
3902}
3903
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003904// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
3905// the ARMInsts array) instead. Getting that here requires awkward
3906// API changes, though. Better way?
3907namespace llvm {
3908extern MCInstrDesc ARMInsts[];
3909}
3910static MCInstrDesc &getInstDesc(unsigned Opcode) {
3911 return ARMInsts[Opcode];
3912}
3913
Jim Grosbach189610f2011-07-26 18:25:39 +00003914// FIXME: We would really like to be able to tablegen'erate this.
3915bool ARMAsmParser::
3916validateInstruction(MCInst &Inst,
3917 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003918 MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
3919 SMLoc Loc = Operands[0]->getStartLoc();
3920 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00003921 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
3922 // being allowed in IT blocks, but not being predicable. It just always
3923 // executes.
3924 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003925 unsigned bit = 1;
3926 if (ITState.FirstCond)
3927 ITState.FirstCond = false;
3928 else
Jim Grosbacha1109882011-09-02 23:22:08 +00003929 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003930 // The instruction must be predicable.
3931 if (!MCID.isPredicable())
3932 return Error(Loc, "instructions in IT block must be predicable");
3933 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
3934 unsigned ITCond = bit ? ITState.Cond :
3935 ARMCC::getOppositeCondition(ITState.Cond);
3936 if (Cond != ITCond) {
3937 // Find the condition code Operand to get its SMLoc information.
3938 SMLoc CondLoc;
3939 for (unsigned i = 1; i < Operands.size(); ++i)
3940 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
3941 CondLoc = Operands[i]->getStartLoc();
3942 return Error(CondLoc, "incorrect condition in IT block; got '" +
3943 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
3944 "', but expected '" +
3945 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
3946 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00003947 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003948 } else if (isThumbTwo() && MCID.isPredicable() &&
3949 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00003950 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
3951 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003952 return Error(Loc, "predicated instructions must be in IT block");
3953
Jim Grosbach189610f2011-07-26 18:25:39 +00003954 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003955 case ARM::LDRD:
3956 case ARM::LDRD_PRE:
3957 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00003958 case ARM::LDREXD: {
3959 // Rt2 must be Rt + 1.
3960 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
3961 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
3962 if (Rt2 != Rt + 1)
3963 return Error(Operands[3]->getStartLoc(),
3964 "destination operands must be sequential");
3965 return false;
3966 }
Jim Grosbach14605d12011-08-11 20:28:23 +00003967 case ARM::STRD: {
3968 // Rt2 must be Rt + 1.
3969 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
3970 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
3971 if (Rt2 != Rt + 1)
3972 return Error(Operands[3]->getStartLoc(),
3973 "source operands must be sequential");
3974 return false;
3975 }
Jim Grosbach53642c52011-08-10 20:49:18 +00003976 case ARM::STRD_PRE:
3977 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00003978 case ARM::STREXD: {
3979 // Rt2 must be Rt + 1.
3980 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
3981 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
3982 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00003983 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00003984 "source operands must be sequential");
3985 return false;
3986 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00003987 case ARM::SBFX:
3988 case ARM::UBFX: {
3989 // width must be in range [1, 32-lsb]
3990 unsigned lsb = Inst.getOperand(2).getImm();
3991 unsigned widthm1 = Inst.getOperand(3).getImm();
3992 if (widthm1 >= 32 - lsb)
3993 return Error(Operands[5]->getStartLoc(),
3994 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00003995 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00003996 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00003997 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00003998 // If we're parsing Thumb2, the .w variant is available and handles
3999 // most cases that are normally illegal for a Thumb1 LDM
4000 // instruction. We'll make the transformation in processInstruction()
4001 // if necessary.
4002 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004003 // Thumb LDM instructions are writeback iff the base register is not
4004 // in the register list.
4005 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004006 bool hasWritebackToken =
4007 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4008 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00004009 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004010 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004011 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4012 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004013 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004014 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004015 return Error(Operands[2]->getStartLoc(),
4016 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004017 // If we should not have writeback, there must not be a '!'. This is
4018 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004019 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004020 return Error(Operands[3]->getStartLoc(),
4021 "writeback operator '!' not allowed when base register "
4022 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004023
4024 break;
4025 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004026 case ARM::t2LDMIA_UPD: {
4027 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
4028 return Error(Operands[4]->getStartLoc(),
4029 "writeback operator '!' not allowed when base register "
4030 "in register list");
4031 break;
4032 }
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004033 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004034 bool listContainsBase;
4035 if (checkLowRegisterList(Inst, 3, 0, ARM::PC, listContainsBase))
4036 return Error(Operands[2]->getStartLoc(),
4037 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004038 break;
4039 }
4040 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004041 bool listContainsBase;
4042 if (checkLowRegisterList(Inst, 3, 0, ARM::LR, listContainsBase))
4043 return Error(Operands[2]->getStartLoc(),
4044 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004045 break;
4046 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00004047 case ARM::tSTMIA_UPD: {
4048 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00004049 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00004050 return Error(Operands[4]->getStartLoc(),
4051 "registers must be in range r0-r7");
4052 break;
4053 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004054 }
4055
4056 return false;
4057}
4058
Jim Grosbachf8fce712011-08-11 17:35:48 +00004059void ARMAsmParser::
4060processInstruction(MCInst &Inst,
4061 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4062 switch (Inst.getOpcode()) {
4063 case ARM::LDMIA_UPD:
4064 // If this is a load of a single register via a 'pop', then we should use
4065 // a post-indexed LDR instruction instead, per the ARM ARM.
4066 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
4067 Inst.getNumOperands() == 5) {
4068 MCInst TmpInst;
4069 TmpInst.setOpcode(ARM::LDR_POST_IMM);
4070 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4071 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4072 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4073 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
4074 TmpInst.addOperand(MCOperand::CreateImm(4));
4075 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4076 TmpInst.addOperand(Inst.getOperand(3));
4077 Inst = TmpInst;
4078 }
4079 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00004080 case ARM::STMDB_UPD:
4081 // If this is a store of a single register via a 'push', then we should use
4082 // a pre-indexed STR instruction instead, per the ARM ARM.
4083 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
4084 Inst.getNumOperands() == 5) {
4085 MCInst TmpInst;
4086 TmpInst.setOpcode(ARM::STR_PRE_IMM);
4087 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4088 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4089 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
4090 TmpInst.addOperand(MCOperand::CreateImm(-4));
4091 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4092 TmpInst.addOperand(Inst.getOperand(3));
4093 Inst = TmpInst;
4094 }
4095 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004096 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00004097 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4098 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4099 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4100 // to encoding T1 if <Rd> is omitted."
4101 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004102 Inst.setOpcode(ARM::tADDi3);
4103 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004104 case ARM::tSUBi8:
4105 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4106 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4107 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4108 // to encoding T1 if <Rd> is omitted."
4109 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
4110 Inst.setOpcode(ARM::tSUBi3);
4111 break;
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004112 case ARM::tB:
4113 // A Thumb conditional branch outside of an IT block is a tBcc.
4114 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4115 Inst.setOpcode(ARM::tBcc);
4116 break;
4117 case ARM::t2B:
4118 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
4119 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4120 Inst.setOpcode(ARM::t2Bcc);
4121 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00004122 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00004123 // If the conditional is AL or we're in an IT block, we really want t2B.
4124 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock())
Jim Grosbachc0755102011-08-31 21:17:31 +00004125 Inst.setOpcode(ARM::t2B);
4126 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00004127 case ARM::tBcc:
4128 // If the conditional is AL, we really want tB.
4129 if (Inst.getOperand(1).getImm() == ARMCC::AL)
4130 Inst.setOpcode(ARM::tB);
Jim Grosbach3ce23d32011-08-18 16:08:39 +00004131 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004132 case ARM::tLDMIA: {
4133 // If the register list contains any high registers, or if the writeback
4134 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
4135 // instead if we're in Thumb2. Otherwise, this should have generated
4136 // an error in validateInstruction().
4137 unsigned Rn = Inst.getOperand(0).getReg();
4138 bool hasWritebackToken =
4139 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4140 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
4141 bool listContainsBase;
4142 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
4143 (!listContainsBase && !hasWritebackToken) ||
4144 (listContainsBase && hasWritebackToken)) {
4145 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4146 assert (isThumbTwo());
4147 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
4148 // If we're switching to the updating version, we need to insert
4149 // the writeback tied operand.
4150 if (hasWritebackToken)
4151 Inst.insert(Inst.begin(),
4152 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
4153 }
4154 break;
4155 }
Jim Grosbach8213c962011-09-16 20:50:13 +00004156 case ARM::tSTMIA_UPD: {
4157 // If the register list contains any high registers, we need to use
4158 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
4159 // should have generated an error in validateInstruction().
4160 unsigned Rn = Inst.getOperand(0).getReg();
4161 bool listContainsBase;
4162 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
4163 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4164 assert (isThumbTwo());
4165 Inst.setOpcode(ARM::t2STMIA_UPD);
4166 }
4167 break;
4168 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004169 case ARM::t2MOVi: {
4170 // If we can use the 16-bit encoding and the user didn't explicitly
4171 // request the 32-bit variant, transform it here.
4172 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4173 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00004174 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
4175 Inst.getOperand(4).getReg() == ARM::CPSR) ||
4176 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004177 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4178 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4179 // The operands aren't in the same order for tMOVi8...
4180 MCInst TmpInst;
4181 TmpInst.setOpcode(ARM::tMOVi8);
4182 TmpInst.addOperand(Inst.getOperand(0));
4183 TmpInst.addOperand(Inst.getOperand(4));
4184 TmpInst.addOperand(Inst.getOperand(1));
4185 TmpInst.addOperand(Inst.getOperand(2));
4186 TmpInst.addOperand(Inst.getOperand(3));
4187 Inst = TmpInst;
4188 }
4189 break;
4190 }
4191 case ARM::t2MOVr: {
4192 // If we can use the 16-bit encoding and the user didn't explicitly
4193 // request the 32-bit variant, transform it here.
4194 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4195 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4196 Inst.getOperand(2).getImm() == ARMCC::AL &&
4197 Inst.getOperand(4).getReg() == ARM::CPSR &&
4198 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4199 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4200 // The operands aren't the same for tMOV[S]r... (no cc_out)
4201 MCInst TmpInst;
4202 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
4203 TmpInst.addOperand(Inst.getOperand(0));
4204 TmpInst.addOperand(Inst.getOperand(1));
4205 TmpInst.addOperand(Inst.getOperand(2));
4206 TmpInst.addOperand(Inst.getOperand(3));
4207 Inst = TmpInst;
4208 }
4209 break;
4210 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004211 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00004212 case ARM::t2SXTB:
4213 case ARM::t2UXTH:
4214 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00004215 // If we can use the 16-bit encoding and the user didn't explicitly
4216 // request the 32-bit variant, transform it here.
4217 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4218 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4219 Inst.getOperand(2).getImm() == 0 &&
4220 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4221 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00004222 unsigned NewOpc;
4223 switch (Inst.getOpcode()) {
4224 default: llvm_unreachable("Illegal opcode!");
4225 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
4226 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
4227 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
4228 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
4229 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004230 // The operands aren't the same for thumb1 (no rotate operand).
4231 MCInst TmpInst;
4232 TmpInst.setOpcode(NewOpc);
4233 TmpInst.addOperand(Inst.getOperand(0));
4234 TmpInst.addOperand(Inst.getOperand(1));
4235 TmpInst.addOperand(Inst.getOperand(3));
4236 TmpInst.addOperand(Inst.getOperand(4));
4237 Inst = TmpInst;
4238 }
4239 break;
4240 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004241 case ARM::t2IT: {
4242 // The mask bits for all but the first condition are represented as
4243 // the low bit of the condition code value implies 't'. We currently
4244 // always have 1 implies 't', so XOR toggle the bits if the low bit
4245 // of the condition code is zero. The encoding also expects the low
4246 // bit of the condition to be encoded as bit 4 of the mask operand,
4247 // so mask that in if needed
4248 MCOperand &MO = Inst.getOperand(1);
4249 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004250 unsigned OrigMask = Mask;
4251 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00004252 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00004253 assert(Mask && TZ <= 3 && "illegal IT mask value!");
4254 for (unsigned i = 3; i != TZ; --i)
4255 Mask ^= 1 << i;
4256 } else
4257 Mask |= 0x10;
4258 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004259
4260 // Set up the IT block state according to the IT instruction we just
4261 // matched.
4262 assert(!inITBlock() && "nested IT blocks?!");
4263 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
4264 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
4265 ITState.CurPosition = 0;
4266 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00004267 break;
4268 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00004269 }
4270}
4271
Jim Grosbach47a0d522011-08-16 20:45:50 +00004272unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
4273 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
4274 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00004275 unsigned Opc = Inst.getOpcode();
4276 MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00004277 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
4278 assert(MCID.hasOptionalDef() &&
4279 "optionally flag setting instruction missing optional def operand");
4280 assert(MCID.NumOperands == Inst.getNumOperands() &&
4281 "operand count mismatch!");
4282 // Find the optional-def operand (cc_out).
4283 unsigned OpNo;
4284 for (OpNo = 0;
4285 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
4286 ++OpNo)
4287 ;
4288 // If we're parsing Thumb1, reject it completely.
4289 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
4290 return Match_MnemonicFail;
4291 // If we're parsing Thumb2, which form is legal depends on whether we're
4292 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004293 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
4294 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00004295 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004296 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
4297 inITBlock())
4298 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004299 }
Jim Grosbach194bd892011-08-16 22:20:01 +00004300 // Some high-register supporting Thumb1 encodings only allow both registers
4301 // to be from r0-r7 when in Thumb2.
4302 else if (Opc == ARM::tADDhirr && isThumbOne() &&
4303 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4304 isARMLowRegister(Inst.getOperand(2).getReg()))
4305 return Match_RequiresThumb2;
4306 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00004307 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00004308 isARMLowRegister(Inst.getOperand(0).getReg()) &&
4309 isARMLowRegister(Inst.getOperand(1).getReg()))
4310 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004311 return Match_Success;
4312}
4313
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004314bool ARMAsmParser::
4315MatchAndEmitInstruction(SMLoc IDLoc,
4316 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
4317 MCStreamer &Out) {
4318 MCInst Inst;
4319 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004320 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004321 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004322 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004323 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004324 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00004325 // Context sensitive operand constraints aren't handled by the matcher,
4326 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00004327 if (validateInstruction(Inst, Operands)) {
4328 // Still progress the IT block, otherwise one wrong condition causes
4329 // nasty cascading errors.
4330 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00004331 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00004332 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004333
Jim Grosbachf8fce712011-08-11 17:35:48 +00004334 // Some instructions need post-processing to, for example, tweak which
4335 // encoding is selected.
4336 processInstruction(Inst, Operands);
4337
Jim Grosbacha1109882011-09-02 23:22:08 +00004338 // Only move forward at the very end so that everything in validate
4339 // and process gets a consistent answer about whether we're in an IT
4340 // block.
4341 forwardITPosition();
4342
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004343 Out.EmitInstruction(Inst);
4344 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004345 case Match_MissingFeature:
4346 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
4347 return true;
4348 case Match_InvalidOperand: {
4349 SMLoc ErrorLoc = IDLoc;
4350 if (ErrorInfo != ~0U) {
4351 if (ErrorInfo >= Operands.size())
4352 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00004353
Chris Lattnere73d4f82010-10-28 21:41:58 +00004354 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
4355 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
4356 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004357
Chris Lattnere73d4f82010-10-28 21:41:58 +00004358 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004359 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00004360 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00004361 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00004362 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004363 // The converter function will have already emited a diagnostic.
4364 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004365 case Match_RequiresNotITBlock:
4366 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00004367 case Match_RequiresITBlock:
4368 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00004369 case Match_RequiresV6:
4370 return Error(IDLoc, "instruction variant requires ARMv6 or later");
4371 case Match_RequiresThumb2:
4372 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00004373 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004374
Eric Christopherc223e2b2010-10-29 09:26:59 +00004375 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00004376 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004377}
4378
Jim Grosbach1355cf12011-07-26 17:10:22 +00004379/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004380bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
4381 StringRef IDVal = DirectiveID.getIdentifier();
4382 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004383 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004384 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004385 return parseDirectiveThumb(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004386 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004387 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004388 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004389 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004390 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004391 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004392 return true;
4393}
4394
Jim Grosbach1355cf12011-07-26 17:10:22 +00004395/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004396/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00004397bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004398 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4399 for (;;) {
4400 const MCExpr *Value;
4401 if (getParser().ParseExpression(Value))
4402 return true;
4403
Chris Lattneraaec2052010-01-19 19:46:13 +00004404 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004405
4406 if (getLexer().is(AsmToken::EndOfStatement))
4407 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00004408
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004409 // FIXME: Improve diagnostic.
4410 if (getLexer().isNot(AsmToken::Comma))
4411 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004412 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004413 }
4414 }
4415
Sean Callananb9a25b72010-01-19 20:27:46 +00004416 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004417 return false;
4418}
4419
Jim Grosbach1355cf12011-07-26 17:10:22 +00004420/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00004421/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00004422bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00004423 if (getLexer().isNot(AsmToken::EndOfStatement))
4424 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004425 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004426
4427 // TODO: set thumb mode
4428 // TODO: tell the MC streamer the mode
4429 // getParser().getStreamer().Emit???();
4430 return false;
4431}
4432
Jim Grosbach1355cf12011-07-26 17:10:22 +00004433/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00004434/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00004435bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00004436 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
4437 bool isMachO = MAI.hasSubsectionsViaSymbols();
4438 StringRef Name;
4439
4440 // Darwin asm has function name after .thumb_func direction
4441 // ELF doesn't
4442 if (isMachO) {
4443 const AsmToken &Tok = Parser.getTok();
4444 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
4445 return Error(L, "unexpected token in .thumb_func directive");
4446 Name = Tok.getString();
4447 Parser.Lex(); // Consume the identifier token.
4448 }
4449
Kevin Enderby515d5092009-10-15 20:48:48 +00004450 if (getLexer().isNot(AsmToken::EndOfStatement))
4451 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004452 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004453
Rafael Espindola64695402011-05-16 16:17:21 +00004454 // FIXME: assuming function name will be the line following .thumb_func
4455 if (!isMachO) {
4456 Name = Parser.getTok().getString();
4457 }
4458
Jim Grosbach642fc9c2010-11-05 22:33:53 +00004459 // Mark symbol as a thumb symbol.
4460 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
4461 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00004462 return false;
4463}
4464
Jim Grosbach1355cf12011-07-26 17:10:22 +00004465/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00004466/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00004467bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00004468 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00004469 if (Tok.isNot(AsmToken::Identifier))
4470 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00004471 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00004472 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00004473 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00004474 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00004475 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00004476 else
4477 return Error(L, "unrecognized syntax mode in .syntax directive");
4478
4479 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00004480 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004481 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004482
4483 // TODO tell the MC streamer the mode
4484 // getParser().getStreamer().Emit???();
4485 return false;
4486}
4487
Jim Grosbach1355cf12011-07-26 17:10:22 +00004488/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00004489/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00004490bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00004491 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00004492 if (Tok.isNot(AsmToken::Integer))
4493 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00004494 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00004495 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00004496 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00004497 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00004498 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004499 else
4500 return Error(L, "invalid operand to .code directive");
4501
4502 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00004503 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004504 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004505
Evan Cheng32869202011-07-08 22:36:29 +00004506 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00004507 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00004508 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00004509 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00004510 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00004511 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00004512 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00004513 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00004514 }
Jim Grosbach2a301702010-11-05 22:40:53 +00004515
Kevin Enderby515d5092009-10-15 20:48:48 +00004516 return false;
4517}
4518
Sean Callanan90b70972010-04-07 20:29:34 +00004519extern "C" void LLVMInitializeARMAsmLexer();
4520
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004521/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004522extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00004523 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
4524 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00004525 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004526}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00004527
Chris Lattner0692ee62010-09-06 19:11:01 +00004528#define GET_REGISTER_MATCHER
4529#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00004530#include "ARMGenAsmMatcher.inc"