blob: 03fba5aee98390bffd05ba24c2aca7e0d65eece6 [file] [log] [blame]
Kevin Enderbyccab3172009-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 Cheng11424442011-07-26 00:24:13 +000010#include "MCTargetDesc/ARMBaseInfo.h"
Evan Chenga20cde32011-07-20 23:34:39 +000011#include "MCTargetDesc/ARMAddressingModes.h"
12#include "MCTargetDesc/ARMMCExpr.h"
Chris Lattner00646cf2010-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 Espindolae90c1cb2011-05-16 16:17:21 +000016#include "llvm/MC/MCAsmInfo.h"
Jim Grosbachc6db8ce2010-11-05 22:33:53 +000017#include "llvm/MC/MCContext.h"
Kevin Enderbyccab3172009-09-15 00:27:25 +000018#include "llvm/MC/MCStreamer.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Evan Cheng4d6c9d72011-08-23 20:15:21 +000021#include "llvm/MC/MCInstrDesc.h"
Evan Cheng11424442011-07-26 00:24:13 +000022#include "llvm/MC/MCRegisterInfo.h"
Evan Cheng4d1ca962011-07-08 01:53:10 +000023#include "llvm/MC/MCSubtargetInfo.h"
Evan Cheng11424442011-07-26 00:24:13 +000024#include "llvm/MC/MCTargetAsmParser.h"
Jim Grosbach3d1eac82011-08-26 21:43:41 +000025#include "llvm/Support/MathExtras.h"
Chris Lattner00646cf2010-01-22 01:44:57 +000026#include "llvm/Support/SourceMgr.h"
Evan Cheng2bb40352011-08-24 18:08:43 +000027#include "llvm/Support/TargetRegistry.h"
Daniel Dunbar4a863e62010-08-11 06:37:12 +000028#include "llvm/Support/raw_ostream.h"
Jim Grosbach5c932b22011-08-22 18:50:36 +000029#include "llvm/ADT/BitVector.h"
Benjamin Kramerdebe69f2011-07-08 21:06:23 +000030#include "llvm/ADT/OwningPtr.h"
Evan Cheng11424442011-07-26 00:24:13 +000031#include "llvm/ADT/STLExtras.h"
Chris Lattner00646cf2010-01-22 01:44:57 +000032#include "llvm/ADT/SmallVector.h"
Owen Andersona098d152011-01-13 22:50:36 +000033#include "llvm/ADT/StringExtras.h"
Daniel Dunbar188b47b2010-08-11 06:37:20 +000034#include "llvm/ADT/StringSwitch.h"
Chris Lattner00646cf2010-01-22 01:44:57 +000035#include "llvm/ADT/Twine.h"
Evan Cheng4d1ca962011-07-08 01:53:10 +000036
Kevin Enderbyccab3172009-09-15 00:27:25 +000037using namespace llvm;
38
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +000039namespace {
Bill Wendlingee7f1f92010-11-06 21:42:12 +000040
41class ARMOperand;
Jim Grosbach624bcc72010-10-29 14:46:02 +000042
Evan Cheng11424442011-07-26 00:24:13 +000043class ARMAsmParser : public MCTargetAsmParser {
Evan Cheng91111d22011-07-09 05:47:46 +000044 MCSubtargetInfo &STI;
Kevin Enderbyccab3172009-09-15 00:27:25 +000045 MCAsmParser &Parser;
46
Jim Grosbached16ec42011-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 Grosbacha0d34d32011-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 Grosbached16ec42011-08-29 22:24:09 +000075
76
Kevin Enderbyccab3172009-09-15 00:27:25 +000077 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyccab3172009-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 Enderbyccab3172009-09-15 00:27:25 +000081 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
82
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000083 int tryParseRegister();
84 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d6022d2011-07-26 20:41:24 +000085 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000086 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd3595712011-08-03 23:50:40 +000087 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000088 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
89 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbachd3595712011-08-03 23:50:40 +000090 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
91 unsigned &ShiftAmount);
Jim Grosbacheab1c0d2011-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 Enderby146dcf22009-10-15 20:48:48 +000097
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000098 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach3d1eac82011-08-26 21:43:41 +000099 bool &CarrySetting, unsigned &ProcessorIMod,
100 StringRef &ITMask);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000101 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +0000102 bool &CanAcceptPredicationCode);
Jim Grosbach624bcc72010-10-29 14:46:02 +0000103
Evan Cheng4d1ca962011-07-08 01:53:10 +0000104 bool isThumb() const {
105 // FIXME: Can tablegen auto-generate this?
Evan Cheng91111d22011-07-09 05:47:46 +0000106 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000107 }
Evan Cheng4d1ca962011-07-08 01:53:10 +0000108 bool isThumbOne() const {
Evan Cheng91111d22011-07-09 05:47:46 +0000109 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000110 }
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000111 bool isThumbTwo() const {
112 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
113 }
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000114 bool hasV6Ops() const {
115 return STI.getFeatureBits() & ARM::HasV6Ops;
116 }
James Molloy21efa7d2011-09-28 14:21:38 +0000117 bool hasV7Ops() const {
118 return STI.getFeatureBits() & ARM::HasV7Ops;
119 }
Evan Cheng284b4672011-07-08 22:36:29 +0000120 void SwitchMode() {
Evan Cheng91111d22011-07-09 05:47:46 +0000121 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
122 setAvailableFeatures(FB);
Evan Cheng284b4672011-07-08 22:36:29 +0000123 }
James Molloy21efa7d2011-09-28 14:21:38 +0000124 bool isMClass() const {
125 return STI.getFeatureBits() & ARM::FeatureMClass;
126 }
Evan Cheng4d1ca962011-07-08 01:53:10 +0000127
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000128 /// @name Auto-generated Match Functions
129 /// {
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +0000130
Chris Lattner3e4582a2010-09-06 19:11:01 +0000131#define GET_ASSEMBLER_HEADER
132#include "ARMGenAsmMatcher.inc"
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000133
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000134 /// }
135
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000136 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000137 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbach861e49c2011-02-12 01:34:40 +0000138 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000139 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbach861e49c2011-02-12 01:34:40 +0000140 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach48399582011-10-12 17:34:41 +0000141 OperandMatchResultTy parseCoprocOptionOperand(
142 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000143 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopescdd20af2011-02-18 19:49:06 +0000144 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000145 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopescdd20af2011-02-18 19:49:06 +0000146 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000147 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopescdd20af2011-02-18 19:49:06 +0000148 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach27c1e252011-07-21 17:23:04 +0000149 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
150 StringRef Op, int Low, int High);
151 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
152 return parsePKHImm(O, "lsl", 0, 31);
153 }
154 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
155 return parsePKHImm(O, "asr", 1, 32);
156 }
Jim Grosbach0a547702011-07-22 17:44:50 +0000157 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000158 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach833b9d32011-07-27 20:15:40 +0000159 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach864b6092011-07-28 21:34:26 +0000160 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachd3595712011-08-03 23:50:40 +0000161 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach1d9d5e92011-08-10 21:56:18 +0000162 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbache7fbce72011-10-03 23:38:36 +0000163 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000164 OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000165
166 // Asm Match Converter Methods
Jim Grosbach7db8d692011-09-08 22:07:06 +0000167 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
168 const SmallVectorImpl<MCParsedAsmOperand*> &);
169 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
170 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachc086f682011-09-08 00:39:19 +0000171 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
172 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach9c0b86a2011-09-16 21:55:56 +0000173 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
174 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000175 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000176 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson16d33f32011-08-26 20:43:14 +0000177 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
178 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd564bf32011-08-11 19:22:40 +0000179 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
180 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000181 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000182 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd886f8c2011-08-11 21:17:22 +0000183 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
184 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd3595712011-08-03 23:50:40 +0000185 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
186 const SmallVectorImpl<MCParsedAsmOperand*> &);
187 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
188 const SmallVectorImpl<MCParsedAsmOperand*> &);
189 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
190 const SmallVectorImpl<MCParsedAsmOperand*> &);
191 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
192 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach5b96b802011-08-10 20:29:19 +0000193 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
194 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheb09f492011-08-11 20:28:23 +0000195 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
196 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachcd4dd252011-08-10 22:42:16 +0000197 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
198 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach8e048492011-08-19 22:07:46 +0000199 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
200 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach3ea06572011-10-24 22:16:58 +0000201 bool cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
202 const SmallVectorImpl<MCParsedAsmOperand*> &);
203 bool cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
204 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000205
206 bool validateInstruction(MCInst &Inst,
207 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach8ba76c62011-08-11 17:35:48 +0000208 void processInstruction(MCInst &Inst,
209 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach7283da92011-08-16 21:12:37 +0000210 bool shouldOmitCCOutOperand(StringRef Mnemonic,
211 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000212
Kevin Enderbyccab3172009-09-15 00:27:25 +0000213public:
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000214 enum ARMMatchResultTy {
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000215 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbached16ec42011-08-29 22:24:09 +0000216 Match_RequiresNotITBlock,
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000217 Match_RequiresV6,
218 Match_RequiresThumb2
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000219 };
220
Evan Cheng91111d22011-07-09 05:47:46 +0000221 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng11424442011-07-26 00:24:13 +0000222 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Cheng4d1ca962011-07-08 01:53:10 +0000223 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng284b4672011-07-08 22:36:29 +0000224
Evan Cheng4d1ca962011-07-08 01:53:10 +0000225 // Initialize the set of available features.
Evan Cheng91111d22011-07-09 05:47:46 +0000226 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbached16ec42011-08-29 22:24:09 +0000227
228 // Not in an ITBlock to start with.
229 ITState.CurPosition = ~0U;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000230 }
Kevin Enderbyccab3172009-09-15 00:27:25 +0000231
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000232 // Implementation of the MCTargetAsmParser interface:
233 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
234 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000235 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000236 bool ParseDirective(AsmToken DirectiveID);
237
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000238 unsigned checkTargetMatchPredicate(MCInst &Inst);
239
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000240 bool MatchAndEmitInstruction(SMLoc IDLoc,
241 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
242 MCStreamer &Out);
Kevin Enderbyccab3172009-09-15 00:27:25 +0000243};
Jim Grosbach624bcc72010-10-29 14:46:02 +0000244} // end anonymous namespace
245
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +0000246namespace {
247
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000248/// ARMOperand - Instances of this class represent a parsed ARM machine
249/// instruction.
Bill Wendlingee7f1f92010-11-06 21:42:12 +0000250class ARMOperand : public MCParsedAsmOperand {
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000251 enum KindTy {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000252 k_CondCode,
253 k_CCOut,
254 k_ITCondMask,
255 k_CoprocNum,
256 k_CoprocReg,
Jim Grosbach48399582011-10-12 17:34:41 +0000257 k_CoprocOption,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000258 k_Immediate,
259 k_FPImmediate,
260 k_MemBarrierOpt,
261 k_Memory,
262 k_PostIndexRegister,
263 k_MSRMask,
264 k_ProcIFlags,
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000265 k_VectorIndex,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000266 k_Register,
267 k_RegisterList,
268 k_DPRRegisterList,
269 k_SPRRegisterList,
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000270 k_VectorList,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000271 k_ShiftedRegister,
272 k_ShiftedImmediate,
273 k_ShifterImmediate,
274 k_RotateImmediate,
275 k_BitfieldDescriptor,
276 k_Token
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000277 } Kind;
278
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000279 SMLoc StartLoc, EndLoc;
Bill Wendling0ab0f672010-11-18 21:50:54 +0000280 SmallVector<unsigned, 8> Registers;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000281
282 union {
283 struct {
Daniel Dunbard8042b72010-08-11 06:36:53 +0000284 ARMCC::CondCodes Val;
285 } CC;
286
287 struct {
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000288 unsigned Val;
289 } Cop;
290
291 struct {
Jim Grosbach48399582011-10-12 17:34:41 +0000292 unsigned Val;
293 } CoprocOption;
294
295 struct {
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000296 unsigned Mask:4;
297 } ITMask;
298
299 struct {
300 ARM_MB::MemBOpt Val;
301 } MBOpt;
302
303 struct {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000304 ARM_PROC::IFlags Val;
305 } IFlags;
306
307 struct {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000308 unsigned Val;
309 } MMask;
310
311 struct {
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000312 const char *Data;
313 unsigned Length;
314 } Tok;
315
316 struct {
317 unsigned RegNum;
318 } Reg;
319
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000320 // A vector register list is a sequential list of 1 to 4 registers.
321 struct {
322 unsigned RegNum;
323 unsigned Count;
324 } VectorList;
325
Bill Wendlingb884a8e2010-11-06 22:19:43 +0000326 struct {
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000327 unsigned Val;
328 } VectorIndex;
329
330 struct {
Kevin Enderbyf5079942009-10-13 22:19:02 +0000331 const MCExpr *Val;
332 } Imm;
Jim Grosbach624bcc72010-10-29 14:46:02 +0000333
Jim Grosbache7fbce72011-10-03 23:38:36 +0000334 struct {
335 unsigned Val; // encoded 8-bit representation
336 } FPImm;
337
Daniel Dunbar2be732a2011-01-10 15:26:21 +0000338 /// Combined record for all forms of ARM address expressions.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000339 struct {
340 unsigned BaseRegNum;
Jim Grosbachd3595712011-08-03 23:50:40 +0000341 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
342 // was specified.
343 const MCConstantExpr *OffsetImm; // Offset immediate value
344 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
345 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbacha95ec992011-10-11 17:29:55 +0000346 unsigned ShiftImm; // shift for OffsetReg.
347 unsigned Alignment; // 0 = no alignment specified
348 // n = alignment in bytes (8, 16, or 32)
Jim Grosbachd3595712011-08-03 23:50:40 +0000349 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbach871dff72011-10-11 15:59:20 +0000350 } Memory;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000351
352 struct {
Jim Grosbachd3595712011-08-03 23:50:40 +0000353 unsigned RegNum;
Jim Grosbachc320c852011-08-05 21:28:30 +0000354 bool isAdd;
355 ARM_AM::ShiftOpc ShiftTy;
356 unsigned ShiftImm;
Jim Grosbachd3595712011-08-03 23:50:40 +0000357 } PostIdxReg;
358
359 struct {
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000360 bool isASR;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000361 unsigned Imm;
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000362 } ShifterImm;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000363 struct {
364 ARM_AM::ShiftOpc ShiftTy;
365 unsigned SrcReg;
366 unsigned ShiftReg;
367 unsigned ShiftImm;
Jim Grosbachac798e12011-07-25 20:49:51 +0000368 } RegShiftedReg;
Owen Andersonb595ed02011-07-21 18:54:16 +0000369 struct {
370 ARM_AM::ShiftOpc ShiftTy;
371 unsigned SrcReg;
372 unsigned ShiftImm;
Jim Grosbachac798e12011-07-25 20:49:51 +0000373 } RegShiftedImm;
Jim Grosbach833b9d32011-07-27 20:15:40 +0000374 struct {
375 unsigned Imm;
376 } RotImm;
Jim Grosbach864b6092011-07-28 21:34:26 +0000377 struct {
378 unsigned LSB;
379 unsigned Width;
380 } Bitfield;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000381 };
Jim Grosbach624bcc72010-10-29 14:46:02 +0000382
Bill Wendlingee7f1f92010-11-06 21:42:12 +0000383 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
384public:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000385 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
386 Kind = o.Kind;
387 StartLoc = o.StartLoc;
388 EndLoc = o.EndLoc;
389 switch (Kind) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000390 case k_CondCode:
Daniel Dunbard8042b72010-08-11 06:36:53 +0000391 CC = o.CC;
392 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000393 case k_ITCondMask:
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000394 ITMask = o.ITMask;
395 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000396 case k_Token:
Daniel Dunbard8042b72010-08-11 06:36:53 +0000397 Tok = o.Tok;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000398 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000399 case k_CCOut:
400 case k_Register:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000401 Reg = o.Reg;
402 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000403 case k_RegisterList:
404 case k_DPRRegisterList:
405 case k_SPRRegisterList:
Bill Wendling0ab0f672010-11-18 21:50:54 +0000406 Registers = o.Registers;
Bill Wendling7cef4472010-11-06 19:56:04 +0000407 break;
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000408 case k_VectorList:
409 VectorList = o.VectorList;
410 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000411 case k_CoprocNum:
412 case k_CoprocReg:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000413 Cop = o.Cop;
414 break;
Jim Grosbach48399582011-10-12 17:34:41 +0000415 case k_CoprocOption:
416 CoprocOption = o.CoprocOption;
417 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000418 case k_Immediate:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000419 Imm = o.Imm;
420 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000421 case k_FPImmediate:
Jim Grosbache7fbce72011-10-03 23:38:36 +0000422 FPImm = o.FPImm;
423 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000424 case k_MemBarrierOpt:
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000425 MBOpt = o.MBOpt;
426 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000427 case k_Memory:
Jim Grosbach871dff72011-10-11 15:59:20 +0000428 Memory = o.Memory;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000429 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000430 case k_PostIndexRegister:
Jim Grosbachd3595712011-08-03 23:50:40 +0000431 PostIdxReg = o.PostIdxReg;
432 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000433 case k_MSRMask:
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000434 MMask = o.MMask;
435 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000436 case k_ProcIFlags:
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000437 IFlags = o.IFlags;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000438 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000439 case k_ShifterImmediate:
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000440 ShifterImm = o.ShifterImm;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000441 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000442 case k_ShiftedRegister:
Jim Grosbachac798e12011-07-25 20:49:51 +0000443 RegShiftedReg = o.RegShiftedReg;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000444 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000445 case k_ShiftedImmediate:
Jim Grosbachac798e12011-07-25 20:49:51 +0000446 RegShiftedImm = o.RegShiftedImm;
Owen Andersonb595ed02011-07-21 18:54:16 +0000447 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000448 case k_RotateImmediate:
Jim Grosbach833b9d32011-07-27 20:15:40 +0000449 RotImm = o.RotImm;
450 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000451 case k_BitfieldDescriptor:
Jim Grosbach864b6092011-07-28 21:34:26 +0000452 Bitfield = o.Bitfield;
453 break;
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000454 case k_VectorIndex:
455 VectorIndex = o.VectorIndex;
456 break;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000457 }
458 }
Jim Grosbach624bcc72010-10-29 14:46:02 +0000459
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000460 /// getStartLoc - Get the location of the first token of this operand.
461 SMLoc getStartLoc() const { return StartLoc; }
462 /// getEndLoc - Get the location of the last token of this operand.
463 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000464
Daniel Dunbard8042b72010-08-11 06:36:53 +0000465 ARMCC::CondCodes getCondCode() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000466 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbard8042b72010-08-11 06:36:53 +0000467 return CC.Val;
468 }
469
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000470 unsigned getCoproc() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000471 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000472 return Cop.Val;
473 }
474
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000475 StringRef getToken() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000476 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000477 return StringRef(Tok.Data, Tok.Length);
478 }
479
480 unsigned getReg() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000481 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling2cae3272010-11-09 22:44:22 +0000482 return Reg.RegNum;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000483 }
484
Bill Wendlingbed94652010-11-09 23:28:44 +0000485 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000486 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
487 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling0ab0f672010-11-18 21:50:54 +0000488 return Registers;
Bill Wendling7cef4472010-11-06 19:56:04 +0000489 }
490
Kevin Enderbyf5079942009-10-13 22:19:02 +0000491 const MCExpr *getImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000492 assert(Kind == k_Immediate && "Invalid access!");
Kevin Enderbyf5079942009-10-13 22:19:02 +0000493 return Imm.Val;
494 }
495
Jim Grosbache7fbce72011-10-03 23:38:36 +0000496 unsigned getFPImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000497 assert(Kind == k_FPImmediate && "Invalid access!");
Jim Grosbache7fbce72011-10-03 23:38:36 +0000498 return FPImm.Val;
499 }
500
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000501 unsigned getVectorIndex() const {
502 assert(Kind == k_VectorIndex && "Invalid access!");
503 return VectorIndex.Val;
504 }
505
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000506 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000507 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000508 return MBOpt.Val;
509 }
510
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000511 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000512 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000513 return IFlags.Val;
514 }
515
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000516 unsigned getMSRMask() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000517 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000518 return MMask.Val;
519 }
520
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000521 bool isCoprocNum() const { return Kind == k_CoprocNum; }
522 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach48399582011-10-12 17:34:41 +0000523 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000524 bool isCondCode() const { return Kind == k_CondCode; }
525 bool isCCOut() const { return Kind == k_CCOut; }
526 bool isITMask() const { return Kind == k_ITCondMask; }
527 bool isITCondCode() const { return Kind == k_CondCode; }
528 bool isImm() const { return Kind == k_Immediate; }
529 bool isFPImm() const { return Kind == k_FPImmediate; }
Jim Grosbach7db8d692011-09-08 22:07:06 +0000530 bool isImm8s4() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000531 if (Kind != k_Immediate)
Jim Grosbach7db8d692011-09-08 22:07:06 +0000532 return false;
533 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
534 if (!CE) return false;
535 int64_t Value = CE->getValue();
536 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
537 }
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000538 bool isImm0_1020s4() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000539 if (Kind != k_Immediate)
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000540 return false;
541 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
542 if (!CE) return false;
543 int64_t Value = CE->getValue();
544 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
545 }
546 bool isImm0_508s4() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000547 if (Kind != k_Immediate)
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000548 return false;
549 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
550 if (!CE) return false;
551 int64_t Value = CE->getValue();
552 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
553 }
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000554 bool isImm0_255() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000555 if (Kind != k_Immediate)
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000556 return false;
557 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
558 if (!CE) return false;
559 int64_t Value = CE->getValue();
560 return Value >= 0 && Value < 256;
561 }
Jim Grosbach31756c22011-07-13 22:01:08 +0000562 bool isImm0_7() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000563 if (Kind != k_Immediate)
Jim Grosbach31756c22011-07-13 22:01:08 +0000564 return false;
565 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
566 if (!CE) return false;
567 int64_t Value = CE->getValue();
568 return Value >= 0 && Value < 8;
569 }
570 bool isImm0_15() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000571 if (Kind != k_Immediate)
Jim Grosbach31756c22011-07-13 22:01:08 +0000572 return false;
573 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
574 if (!CE) return false;
575 int64_t Value = CE->getValue();
576 return Value >= 0 && Value < 16;
577 }
Jim Grosbach72e7c4f2011-07-21 23:26:25 +0000578 bool isImm0_31() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000579 if (Kind != k_Immediate)
Jim Grosbach72e7c4f2011-07-21 23:26:25 +0000580 return false;
581 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
582 if (!CE) return false;
583 int64_t Value = CE->getValue();
584 return Value >= 0 && Value < 32;
585 }
Jim Grosbach475c6db2011-07-25 23:09:14 +0000586 bool isImm1_16() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000587 if (Kind != k_Immediate)
Jim Grosbach475c6db2011-07-25 23:09:14 +0000588 return false;
589 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
590 if (!CE) return false;
591 int64_t Value = CE->getValue();
592 return Value > 0 && Value < 17;
593 }
Jim Grosbach801e0a32011-07-22 23:16:18 +0000594 bool isImm1_32() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000595 if (Kind != k_Immediate)
Jim Grosbach801e0a32011-07-22 23:16:18 +0000596 return false;
597 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
598 if (!CE) return false;
599 int64_t Value = CE->getValue();
600 return Value > 0 && Value < 33;
601 }
Jim Grosbach975b6412011-07-13 20:10:10 +0000602 bool isImm0_65535() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000603 if (Kind != k_Immediate)
Jim Grosbach975b6412011-07-13 20:10:10 +0000604 return false;
605 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
606 if (!CE) return false;
607 int64_t Value = CE->getValue();
608 return Value >= 0 && Value < 65536;
609 }
Jim Grosbach7c09e3c2011-07-19 19:13:28 +0000610 bool isImm0_65535Expr() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000611 if (Kind != k_Immediate)
Jim Grosbach7c09e3c2011-07-19 19:13:28 +0000612 return false;
613 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
614 // If it's not a constant expression, it'll generate a fixup and be
615 // handled later.
616 if (!CE) return true;
617 int64_t Value = CE->getValue();
618 return Value >= 0 && Value < 65536;
619 }
Jim Grosbachf1637842011-07-26 16:24:27 +0000620 bool isImm24bit() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000621 if (Kind != k_Immediate)
Jim Grosbachf1637842011-07-26 16:24:27 +0000622 return false;
623 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
624 if (!CE) return false;
625 int64_t Value = CE->getValue();
626 return Value >= 0 && Value <= 0xffffff;
627 }
Jim Grosbach46dd4132011-08-17 21:51:27 +0000628 bool isImmThumbSR() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000629 if (Kind != k_Immediate)
Jim Grosbach46dd4132011-08-17 21:51:27 +0000630 return false;
631 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
632 if (!CE) return false;
633 int64_t Value = CE->getValue();
634 return Value > 0 && Value < 33;
635 }
Jim Grosbach27c1e252011-07-21 17:23:04 +0000636 bool isPKHLSLImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000637 if (Kind != k_Immediate)
Jim Grosbach27c1e252011-07-21 17:23:04 +0000638 return false;
639 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
640 if (!CE) return false;
641 int64_t Value = CE->getValue();
642 return Value >= 0 && Value < 32;
643 }
644 bool isPKHASRImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000645 if (Kind != k_Immediate)
Jim Grosbach27c1e252011-07-21 17:23:04 +0000646 return false;
647 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
648 if (!CE) return false;
649 int64_t Value = CE->getValue();
650 return Value > 0 && Value <= 32;
651 }
Jim Grosbach9720dcf2011-07-19 16:50:30 +0000652 bool isARMSOImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000653 if (Kind != k_Immediate)
Jim Grosbach9720dcf2011-07-19 16:50:30 +0000654 return false;
655 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
656 if (!CE) return false;
657 int64_t Value = CE->getValue();
658 return ARM_AM::getSOImmVal(Value) != -1;
659 }
Jim Grosbach3d785ed2011-10-28 22:50:54 +0000660 bool isARMSOImmNot() const {
661 if (Kind != k_Immediate)
662 return false;
663 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
664 if (!CE) return false;
665 int64_t Value = CE->getValue();
666 return ARM_AM::getSOImmVal(~Value) != -1;
667 }
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000668 bool isT2SOImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000669 if (Kind != k_Immediate)
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000670 return false;
671 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
672 if (!CE) return false;
673 int64_t Value = CE->getValue();
674 return ARM_AM::getT2SOImmVal(Value) != -1;
675 }
Jim Grosbachb009a872011-10-28 22:36:30 +0000676 bool isT2SOImmNot() const {
677 if (Kind != k_Immediate)
678 return false;
679 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
680 if (!CE) return false;
681 int64_t Value = CE->getValue();
682 return ARM_AM::getT2SOImmVal(~Value) != -1;
683 }
Jim Grosbach0a547702011-07-22 17:44:50 +0000684 bool isSetEndImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000685 if (Kind != k_Immediate)
Jim Grosbach0a547702011-07-22 17:44:50 +0000686 return false;
687 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
688 if (!CE) return false;
689 int64_t Value = CE->getValue();
690 return Value == 1 || Value == 0;
691 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000692 bool isReg() const { return Kind == k_Register; }
693 bool isRegList() const { return Kind == k_RegisterList; }
694 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
695 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
696 bool isToken() const { return Kind == k_Token; }
697 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
698 bool isMemory() const { return Kind == k_Memory; }
699 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
700 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
701 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
702 bool isRotImm() const { return Kind == k_RotateImmediate; }
703 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
704 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachc320c852011-08-05 21:28:30 +0000705 bool isPostIdxReg() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000706 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy == ARM_AM::no_shift;
Jim Grosbachc320c852011-08-05 21:28:30 +0000707 }
Jim Grosbacha95ec992011-10-11 17:29:55 +0000708 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachc11b7c32011-10-10 23:06:42 +0000709 if (!isMemory())
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000710 return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000711 // No offset of any kind.
Jim Grosbacha95ec992011-10-11 17:29:55 +0000712 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
713 (alignOK || Memory.Alignment == 0);
714 }
715 bool isAlignedMemory() const {
716 return isMemNoOffset(true);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000717 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000718 bool isAddrMode2() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000719 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000720 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000721 if (Memory.OffsetRegNum) return true;
Jim Grosbachd3595712011-08-03 23:50:40 +0000722 // Immediate offset in range [-4095, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +0000723 if (!Memory.OffsetImm) return true;
724 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachd3595712011-08-03 23:50:40 +0000725 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +0000726 }
Jim Grosbachcd17c122011-08-04 23:01:30 +0000727 bool isAM2OffsetImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000728 if (Kind != k_Immediate)
Jim Grosbachcd17c122011-08-04 23:01:30 +0000729 return false;
730 // Immediate offset in range [-4095, 4095].
731 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
732 if (!CE) return false;
733 int64_t Val = CE->getValue();
734 return Val > -4096 && Val < 4096;
735 }
Jim Grosbach5b96b802011-08-10 20:29:19 +0000736 bool isAddrMode3() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000737 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000738 // No shifts are legal for AM3.
Jim Grosbach871dff72011-10-11 15:59:20 +0000739 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000740 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000741 if (Memory.OffsetRegNum) return true;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000742 // Immediate offset in range [-255, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +0000743 if (!Memory.OffsetImm) return true;
744 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach5b96b802011-08-10 20:29:19 +0000745 return Val > -256 && Val < 256;
746 }
747 bool isAM3Offset() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000748 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach5b96b802011-08-10 20:29:19 +0000749 return false;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000750 if (Kind == k_PostIndexRegister)
Jim Grosbach5b96b802011-08-10 20:29:19 +0000751 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
752 // Immediate offset in range [-255, 255].
753 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
754 if (!CE) return false;
755 int64_t Val = CE->getValue();
Jim Grosbach1d9d5e92011-08-10 21:56:18 +0000756 // Special case, #-0 is INT32_MIN.
757 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000758 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000759 bool isAddrMode5() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000760 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000761 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000762 if (Memory.OffsetRegNum) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000763 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbach871dff72011-10-11 15:59:20 +0000764 if (!Memory.OffsetImm) return true;
765 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson967674d2011-08-29 19:36:44 +0000766 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
767 Val == INT32_MIN;
Bill Wendling8d2aa032010-11-08 23:49:57 +0000768 }
Jim Grosbach05541f42011-09-19 22:21:13 +0000769 bool isMemTBB() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000770 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000771 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach05541f42011-09-19 22:21:13 +0000772 return false;
773 return true;
774 }
775 bool isMemTBH() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000776 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000777 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
778 Memory.Alignment != 0 )
Jim Grosbach05541f42011-09-19 22:21:13 +0000779 return false;
780 return true;
781 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000782 bool isMemRegOffset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000783 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendling092a7bd2010-12-14 03:36:38 +0000784 return false;
Daniel Dunbar7ed45592011-01-18 05:34:11 +0000785 return true;
Bill Wendling092a7bd2010-12-14 03:36:38 +0000786 }
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000787 bool isT2MemRegOffset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000788 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
789 Memory.Alignment != 0)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000790 return false;
791 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbach871dff72011-10-11 15:59:20 +0000792 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000793 return true;
Jim Grosbach871dff72011-10-11 15:59:20 +0000794 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000795 return false;
796 return true;
797 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000798 bool isMemThumbRR() const {
799 // Thumb reg+reg addressing is simple. Just two registers, a base and
800 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbach871dff72011-10-11 15:59:20 +0000801 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000802 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendling811c9362010-11-30 07:44:32 +0000803 return false;
Jim Grosbach871dff72011-10-11 15:59:20 +0000804 return isARMLowRegister(Memory.BaseRegNum) &&
805 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach3fe94e32011-08-19 17:55:24 +0000806 }
807 bool isMemThumbRIs4() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000808 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000809 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach3fe94e32011-08-19 17:55:24 +0000810 return false;
811 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbach871dff72011-10-11 15:59:20 +0000812 if (!Memory.OffsetImm) return true;
813 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach23983d62011-08-19 18:13:48 +0000814 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
815 }
Jim Grosbach26d35872011-08-19 18:55:51 +0000816 bool isMemThumbRIs2() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000817 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000818 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach26d35872011-08-19 18:55:51 +0000819 return false;
820 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbach871dff72011-10-11 15:59:20 +0000821 if (!Memory.OffsetImm) return true;
822 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach26d35872011-08-19 18:55:51 +0000823 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
824 }
Jim Grosbacha32c7532011-08-19 18:49:59 +0000825 bool isMemThumbRIs1() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000826 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000827 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbacha32c7532011-08-19 18:49:59 +0000828 return false;
829 // Immediate offset in range [0, 31].
Jim Grosbach871dff72011-10-11 15:59:20 +0000830 if (!Memory.OffsetImm) return true;
831 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha32c7532011-08-19 18:49:59 +0000832 return Val >= 0 && Val <= 31;
833 }
Jim Grosbach23983d62011-08-19 18:13:48 +0000834 bool isMemThumbSPI() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000835 if (!isMemory() || Memory.OffsetRegNum != 0 ||
836 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbach23983d62011-08-19 18:13:48 +0000837 return false;
838 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +0000839 if (!Memory.OffsetImm) return true;
840 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach23983d62011-08-19 18:13:48 +0000841 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendling811c9362010-11-30 07:44:32 +0000842 }
Jim Grosbach7db8d692011-09-08 22:07:06 +0000843 bool isMemImm8s4Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000844 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7db8d692011-09-08 22:07:06 +0000845 return false;
846 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +0000847 if (!Memory.OffsetImm) return true;
848 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7db8d692011-09-08 22:07:06 +0000849 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
850 }
Jim Grosbacha05627e2011-09-09 18:37:27 +0000851 bool isMemImm0_1020s4Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000852 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha05627e2011-09-09 18:37:27 +0000853 return false;
854 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +0000855 if (!Memory.OffsetImm) return true;
856 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha05627e2011-09-09 18:37:27 +0000857 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
858 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000859 bool isMemImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000860 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachd3595712011-08-03 23:50:40 +0000861 return false;
862 // Immediate offset in range [-255, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +0000863 if (!Memory.OffsetImm) return true;
864 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson49168402011-09-23 22:25:02 +0000865 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbachd3595712011-08-03 23:50:40 +0000866 }
Jim Grosbach2392c532011-09-07 23:39:14 +0000867 bool isMemPosImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000868 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach2392c532011-09-07 23:39:14 +0000869 return false;
870 // Immediate offset in range [0, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +0000871 if (!Memory.OffsetImm) return true;
872 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2392c532011-09-07 23:39:14 +0000873 return Val >= 0 && Val < 256;
874 }
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +0000875 bool isMemNegImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000876 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +0000877 return false;
878 // Immediate offset in range [-255, -1].
Jim Grosbach871dff72011-10-11 15:59:20 +0000879 if (!Memory.OffsetImm) return true;
880 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +0000881 return Val > -256 && Val < 0;
882 }
883 bool isMemUImm12Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000884 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +0000885 return false;
886 // Immediate offset in range [0, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +0000887 if (!Memory.OffsetImm) return true;
888 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +0000889 return (Val >= 0 && Val < 4096);
890 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000891 bool isMemImm12Offset() const {
Jim Grosbach95466ce2011-08-08 20:59:31 +0000892 // If we have an immediate that's not a constant, treat it as a label
893 // reference needing a fixup. If it is a constant, it's something else
894 // and we reject it.
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000895 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach95466ce2011-08-08 20:59:31 +0000896 return true;
897
Jim Grosbacha95ec992011-10-11 17:29:55 +0000898 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachd3595712011-08-03 23:50:40 +0000899 return false;
900 // Immediate offset in range [-4095, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +0000901 if (!Memory.OffsetImm) return true;
902 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson967674d2011-08-29 19:36:44 +0000903 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbachd3595712011-08-03 23:50:40 +0000904 }
905 bool isPostIdxImm8() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000906 if (Kind != k_Immediate)
Jim Grosbachd3595712011-08-03 23:50:40 +0000907 return false;
908 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
909 if (!CE) return false;
910 int64_t Val = CE->getValue();
Owen Andersonf02d98d2011-08-29 17:17:09 +0000911 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbachd3595712011-08-03 23:50:40 +0000912 }
Jim Grosbach93981412011-10-11 21:55:36 +0000913 bool isPostIdxImm8s4() const {
914 if (Kind != k_Immediate)
915 return false;
916 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
917 if (!CE) return false;
918 int64_t Val = CE->getValue();
919 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
920 (Val == INT32_MIN);
921 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000922
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000923 bool isMSRMask() const { return Kind == k_MSRMask; }
924 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +0000925
Jim Grosbach741cd732011-10-17 22:26:03 +0000926 // NEON operands.
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000927 bool isVecListOneD() const {
928 if (Kind != k_VectorList) return false;
929 return VectorList.Count == 1;
930 }
931
Jim Grosbach2f2e3c42011-10-21 18:54:25 +0000932 bool isVecListTwoD() const {
933 if (Kind != k_VectorList) return false;
934 return VectorList.Count == 2;
935 }
936
Jim Grosbachc4360fe2011-10-21 20:02:19 +0000937 bool isVecListThreeD() const {
938 if (Kind != k_VectorList) return false;
939 return VectorList.Count == 3;
940 }
941
Jim Grosbach846bcff2011-10-21 20:35:01 +0000942 bool isVecListFourD() const {
943 if (Kind != k_VectorList) return false;
944 return VectorList.Count == 4;
945 }
946
Jim Grosbach118b38c2011-10-21 22:21:10 +0000947 bool isVecListTwoQ() const {
948 if (Kind != k_VectorList) return false;
949 //FIXME: We haven't taught the parser to handle by-two register lists
950 // yet, so don't pretend to know one.
951 return VectorList.Count == 2 && false;
952 }
953
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000954 bool isVectorIndex8() const {
955 if (Kind != k_VectorIndex) return false;
956 return VectorIndex.Val < 8;
957 }
958 bool isVectorIndex16() const {
959 if (Kind != k_VectorIndex) return false;
960 return VectorIndex.Val < 4;
961 }
962 bool isVectorIndex32() const {
963 if (Kind != k_VectorIndex) return false;
964 return VectorIndex.Val < 2;
965 }
966
Jim Grosbach741cd732011-10-17 22:26:03 +0000967 bool isNEONi8splat() const {
968 if (Kind != k_Immediate)
969 return false;
970 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
971 // Must be a constant.
972 if (!CE) return false;
973 int64_t Value = CE->getValue();
974 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
975 // value.
Jim Grosbach741cd732011-10-17 22:26:03 +0000976 return Value >= 0 && Value < 256;
977 }
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000978
Jim Grosbachcda32ae2011-10-17 23:09:09 +0000979 bool isNEONi16splat() const {
980 if (Kind != k_Immediate)
981 return false;
982 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
983 // Must be a constant.
984 if (!CE) return false;
985 int64_t Value = CE->getValue();
986 // i16 value in the range [0,255] or [0x0100, 0xff00]
987 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
988 }
989
Jim Grosbach8211c052011-10-18 00:22:00 +0000990 bool isNEONi32splat() const {
991 if (Kind != k_Immediate)
992 return false;
993 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
994 // Must be a constant.
995 if (!CE) return false;
996 int64_t Value = CE->getValue();
997 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
998 return (Value >= 0 && Value < 256) ||
999 (Value >= 0x0100 && Value <= 0xff00) ||
1000 (Value >= 0x010000 && Value <= 0xff0000) ||
1001 (Value >= 0x01000000 && Value <= 0xff000000);
1002 }
1003
1004 bool isNEONi32vmov() const {
1005 if (Kind != k_Immediate)
1006 return false;
1007 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1008 // Must be a constant.
1009 if (!CE) return false;
1010 int64_t Value = CE->getValue();
1011 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1012 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1013 return (Value >= 0 && Value < 256) ||
1014 (Value >= 0x0100 && Value <= 0xff00) ||
1015 (Value >= 0x010000 && Value <= 0xff0000) ||
1016 (Value >= 0x01000000 && Value <= 0xff000000) ||
1017 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1018 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1019 }
1020
Jim Grosbache4454e02011-10-18 16:18:11 +00001021 bool isNEONi64splat() const {
1022 if (Kind != k_Immediate)
1023 return false;
1024 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1025 // Must be a constant.
1026 if (!CE) return false;
1027 uint64_t Value = CE->getValue();
1028 // i64 value with each byte being either 0 or 0xff.
1029 for (unsigned i = 0; i < 8; ++i)
1030 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1031 return true;
1032 }
1033
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001034 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner5d6f6a02010-10-29 00:27:31 +00001035 // Add as immediates when possible. Null MCExpr = 0.
1036 if (Expr == 0)
1037 Inst.addOperand(MCOperand::CreateImm(0));
1038 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001039 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1040 else
1041 Inst.addOperand(MCOperand::CreateExpr(Expr));
1042 }
1043
Daniel Dunbard8042b72010-08-11 06:36:53 +00001044 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001045 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbard8042b72010-08-11 06:36:53 +00001046 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach968c9272010-12-06 18:30:57 +00001047 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1048 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbard8042b72010-08-11 06:36:53 +00001049 }
1050
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001051 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1052 assert(N == 1 && "Invalid number of operands!");
1053 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1054 }
1055
Jim Grosbach48399582011-10-12 17:34:41 +00001056 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1057 assert(N == 1 && "Invalid number of operands!");
1058 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1059 }
1060
1061 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1062 assert(N == 1 && "Invalid number of operands!");
1063 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1064 }
1065
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001066 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1067 assert(N == 1 && "Invalid number of operands!");
1068 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1069 }
1070
1071 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1072 assert(N == 1 && "Invalid number of operands!");
1073 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1074 }
1075
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001076 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1077 assert(N == 1 && "Invalid number of operands!");
1078 Inst.addOperand(MCOperand::CreateReg(getReg()));
1079 }
1080
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001081 void addRegOperands(MCInst &Inst, unsigned N) const {
1082 assert(N == 1 && "Invalid number of operands!");
1083 Inst.addOperand(MCOperand::CreateReg(getReg()));
1084 }
1085
Jim Grosbachac798e12011-07-25 20:49:51 +00001086 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001087 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachac798e12011-07-25 20:49:51 +00001088 assert(isRegShiftedReg() && "addRegShiftedRegOperands() on non RegShiftedReg!");
1089 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1090 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001091 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachac798e12011-07-25 20:49:51 +00001092 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001093 }
1094
Jim Grosbachac798e12011-07-25 20:49:51 +00001095 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson04912702011-07-21 23:38:37 +00001096 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachac798e12011-07-25 20:49:51 +00001097 assert(isRegShiftedImm() && "addRegShiftedImmOperands() on non RegShiftedImm!");
1098 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Andersonb595ed02011-07-21 18:54:16 +00001099 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachac798e12011-07-25 20:49:51 +00001100 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Andersonb595ed02011-07-21 18:54:16 +00001101 }
1102
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001103 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001104 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001105 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1106 ShifterImm.Imm));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001107 }
1108
Bill Wendling8d2aa032010-11-08 23:49:57 +00001109 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling2cae3272010-11-09 22:44:22 +00001110 assert(N == 1 && "Invalid number of operands!");
Bill Wendlingbed94652010-11-09 23:28:44 +00001111 const SmallVectorImpl<unsigned> &RegList = getRegList();
1112 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00001113 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1114 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling8d2aa032010-11-08 23:49:57 +00001115 }
1116
Bill Wendling9898ac92010-11-17 04:32:08 +00001117 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1118 addRegListOperands(Inst, N);
1119 }
1120
1121 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1122 addRegListOperands(Inst, N);
1123 }
1124
Jim Grosbach833b9d32011-07-27 20:15:40 +00001125 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1126 assert(N == 1 && "Invalid number of operands!");
1127 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1128 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1129 }
1130
Jim Grosbach864b6092011-07-28 21:34:26 +00001131 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1132 assert(N == 1 && "Invalid number of operands!");
1133 // Munge the lsb/width into a bitfield mask.
1134 unsigned lsb = Bitfield.LSB;
1135 unsigned width = Bitfield.Width;
1136 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1137 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1138 (32 - (lsb + width)));
1139 Inst.addOperand(MCOperand::CreateImm(Mask));
1140 }
1141
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001142 void addImmOperands(MCInst &Inst, unsigned N) const {
1143 assert(N == 1 && "Invalid number of operands!");
1144 addExpr(Inst, getImm());
1145 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00001146
Jim Grosbache7fbce72011-10-03 23:38:36 +00001147 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1148 assert(N == 1 && "Invalid number of operands!");
1149 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1150 }
1151
Jim Grosbach7db8d692011-09-08 22:07:06 +00001152 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1153 assert(N == 1 && "Invalid number of operands!");
1154 // FIXME: We really want to scale the value here, but the LDRD/STRD
1155 // instruction don't encode operands that way yet.
1156 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1157 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1158 }
1159
Jim Grosbach0a0b3072011-08-24 21:22:15 +00001160 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1161 assert(N == 1 && "Invalid number of operands!");
1162 // The immediate is scaled by four in the encoding and is stored
1163 // in the MCInst as such. Lop off the low two bits here.
1164 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1165 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1166 }
1167
1168 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1169 assert(N == 1 && "Invalid number of operands!");
1170 // The immediate is scaled by four in the encoding and is stored
1171 // in the MCInst as such. Lop off the low two bits here.
1172 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1173 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1174 }
1175
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +00001176 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1177 assert(N == 1 && "Invalid number of operands!");
1178 addExpr(Inst, getImm());
1179 }
1180
Jim Grosbach31756c22011-07-13 22:01:08 +00001181 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1182 assert(N == 1 && "Invalid number of operands!");
1183 addExpr(Inst, getImm());
1184 }
1185
1186 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1187 assert(N == 1 && "Invalid number of operands!");
1188 addExpr(Inst, getImm());
1189 }
1190
Jim Grosbach72e7c4f2011-07-21 23:26:25 +00001191 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1192 assert(N == 1 && "Invalid number of operands!");
1193 addExpr(Inst, getImm());
1194 }
1195
Jim Grosbach475c6db2011-07-25 23:09:14 +00001196 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1197 assert(N == 1 && "Invalid number of operands!");
1198 // The constant encodes as the immediate-1, and we store in the instruction
1199 // the bits as encoded, so subtract off one here.
1200 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1201 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1202 }
1203
Jim Grosbach801e0a32011-07-22 23:16:18 +00001204 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1205 assert(N == 1 && "Invalid number of operands!");
1206 // The constant encodes as the immediate-1, and we store in the instruction
1207 // the bits as encoded, so subtract off one here.
1208 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1209 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1210 }
1211
Jim Grosbach975b6412011-07-13 20:10:10 +00001212 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1213 assert(N == 1 && "Invalid number of operands!");
1214 addExpr(Inst, getImm());
1215 }
1216
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00001217 void addImm0_65535ExprOperands(MCInst &Inst, unsigned N) const {
1218 assert(N == 1 && "Invalid number of operands!");
1219 addExpr(Inst, getImm());
1220 }
1221
Jim Grosbachf1637842011-07-26 16:24:27 +00001222 void addImm24bitOperands(MCInst &Inst, unsigned N) const {
1223 assert(N == 1 && "Invalid number of operands!");
1224 addExpr(Inst, getImm());
1225 }
1226
Jim Grosbach46dd4132011-08-17 21:51:27 +00001227 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1228 assert(N == 1 && "Invalid number of operands!");
1229 // The constant encodes as the immediate, except for 32, which encodes as
1230 // zero.
1231 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1232 unsigned Imm = CE->getValue();
1233 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1234 }
1235
Jim Grosbach27c1e252011-07-21 17:23:04 +00001236 void addPKHLSLImmOperands(MCInst &Inst, unsigned N) const {
1237 assert(N == 1 && "Invalid number of operands!");
1238 addExpr(Inst, getImm());
1239 }
1240
1241 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1242 assert(N == 1 && "Invalid number of operands!");
1243 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1244 // the instruction as well.
1245 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1246 int Val = CE->getValue();
1247 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1248 }
1249
Jim Grosbach9720dcf2011-07-19 16:50:30 +00001250 void addARMSOImmOperands(MCInst &Inst, unsigned N) const {
1251 assert(N == 1 && "Invalid number of operands!");
1252 addExpr(Inst, getImm());
1253 }
1254
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +00001255 void addT2SOImmOperands(MCInst &Inst, unsigned N) const {
1256 assert(N == 1 && "Invalid number of operands!");
1257 addExpr(Inst, getImm());
1258 }
1259
Jim Grosbachb009a872011-10-28 22:36:30 +00001260 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1261 assert(N == 1 && "Invalid number of operands!");
1262 // The operand is actually a t2_so_imm, but we have its bitwise
1263 // negation in the assembly source, so twiddle it here.
1264 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1265 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1266 }
1267
Jim Grosbach3d785ed2011-10-28 22:50:54 +00001268 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1269 assert(N == 1 && "Invalid number of operands!");
1270 // The operand is actually a so_imm, but we have its bitwise
1271 // negation in the assembly source, so twiddle it here.
1272 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1273 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1274 }
1275
Jim Grosbach0a547702011-07-22 17:44:50 +00001276 void addSetEndImmOperands(MCInst &Inst, unsigned N) const {
1277 assert(N == 1 && "Invalid number of operands!");
1278 addExpr(Inst, getImm());
1279 }
1280
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001281 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1282 assert(N == 1 && "Invalid number of operands!");
1283 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1284 }
1285
Jim Grosbachd3595712011-08-03 23:50:40 +00001286 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1287 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001288 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopesf170f8b2011-03-24 21:04:58 +00001289 }
1290
Jim Grosbacha95ec992011-10-11 17:29:55 +00001291 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1292 assert(N == 2 && "Invalid number of operands!");
1293 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1294 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1295 }
1296
Jim Grosbachd3595712011-08-03 23:50:40 +00001297 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1298 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001299 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1300 if (!Memory.OffsetRegNum) {
Jim Grosbachd3595712011-08-03 23:50:40 +00001301 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1302 // Special case for #-0
1303 if (Val == INT32_MIN) Val = 0;
1304 if (Val < 0) Val = -Val;
1305 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1306 } else {
1307 // For register offset, we encode the shift type and negation flag
1308 // here.
Jim Grosbach871dff72011-10-11 15:59:20 +00001309 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1310 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001311 }
Jim Grosbach871dff72011-10-11 15:59:20 +00001312 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1313 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001314 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001315 }
1316
Jim Grosbachcd17c122011-08-04 23:01:30 +00001317 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1318 assert(N == 2 && "Invalid number of operands!");
1319 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1320 assert(CE && "non-constant AM2OffsetImm operand!");
1321 int32_t Val = CE->getValue();
1322 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1323 // Special case for #-0
1324 if (Val == INT32_MIN) Val = 0;
1325 if (Val < 0) Val = -Val;
1326 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1327 Inst.addOperand(MCOperand::CreateReg(0));
1328 Inst.addOperand(MCOperand::CreateImm(Val));
1329 }
1330
Jim Grosbach5b96b802011-08-10 20:29:19 +00001331 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1332 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001333 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1334 if (!Memory.OffsetRegNum) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00001335 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1336 // Special case for #-0
1337 if (Val == INT32_MIN) Val = 0;
1338 if (Val < 0) Val = -Val;
1339 Val = ARM_AM::getAM3Opc(AddSub, Val);
1340 } else {
1341 // For register offset, we encode the shift type and negation flag
1342 // here.
Jim Grosbach871dff72011-10-11 15:59:20 +00001343 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach5b96b802011-08-10 20:29:19 +00001344 }
Jim Grosbach871dff72011-10-11 15:59:20 +00001345 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1346 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach5b96b802011-08-10 20:29:19 +00001347 Inst.addOperand(MCOperand::CreateImm(Val));
1348 }
1349
1350 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1351 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001352 if (Kind == k_PostIndexRegister) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00001353 int32_t Val =
1354 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1355 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1356 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001357 return;
Jim Grosbach5b96b802011-08-10 20:29:19 +00001358 }
1359
1360 // Constant offset.
1361 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1362 int32_t Val = CE->getValue();
1363 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1364 // Special case for #-0
1365 if (Val == INT32_MIN) Val = 0;
1366 if (Val < 0) Val = -Val;
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001367 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach5b96b802011-08-10 20:29:19 +00001368 Inst.addOperand(MCOperand::CreateReg(0));
1369 Inst.addOperand(MCOperand::CreateImm(Val));
1370 }
1371
Jim Grosbachd3595712011-08-03 23:50:40 +00001372 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1373 assert(N == 2 && "Invalid number of operands!");
1374 // The lower two bits are always zero and as such are not encoded.
Jim Grosbach871dff72011-10-11 15:59:20 +00001375 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00001376 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1377 // Special case for #-0
1378 if (Val == INT32_MIN) Val = 0;
1379 if (Val < 0) Val = -Val;
1380 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbach871dff72011-10-11 15:59:20 +00001381 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001382 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00001383 }
1384
Jim Grosbach7db8d692011-09-08 22:07:06 +00001385 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1386 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001387 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1388 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7db8d692011-09-08 22:07:06 +00001389 Inst.addOperand(MCOperand::CreateImm(Val));
1390 }
1391
Jim Grosbacha05627e2011-09-09 18:37:27 +00001392 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1393 assert(N == 2 && "Invalid number of operands!");
1394 // The lower two bits are always zero and as such are not encoded.
Jim Grosbach871dff72011-10-11 15:59:20 +00001395 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1396 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha05627e2011-09-09 18:37:27 +00001397 Inst.addOperand(MCOperand::CreateImm(Val));
1398 }
1399
Jim Grosbachd3595712011-08-03 23:50:40 +00001400 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1401 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001402 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1403 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001404 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner5d6f6a02010-10-29 00:27:31 +00001405 }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001406
Jim Grosbach2392c532011-09-07 23:39:14 +00001407 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1408 addMemImm8OffsetOperands(Inst, N);
1409 }
1410
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001411 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach2392c532011-09-07 23:39:14 +00001412 addMemImm8OffsetOperands(Inst, N);
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001413 }
1414
1415 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1416 assert(N == 2 && "Invalid number of operands!");
1417 // If this is an immediate, it's a label reference.
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001418 if (Kind == k_Immediate) {
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001419 addExpr(Inst, getImm());
1420 Inst.addOperand(MCOperand::CreateImm(0));
1421 return;
1422 }
1423
1424 // Otherwise, it's a normal memory reg+offset.
Jim Grosbach871dff72011-10-11 15:59:20 +00001425 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1426 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001427 Inst.addOperand(MCOperand::CreateImm(Val));
1428 }
1429
Jim Grosbachd3595712011-08-03 23:50:40 +00001430 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1431 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach95466ce2011-08-08 20:59:31 +00001432 // If this is an immediate, it's a label reference.
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001433 if (Kind == k_Immediate) {
Jim Grosbach95466ce2011-08-08 20:59:31 +00001434 addExpr(Inst, getImm());
1435 Inst.addOperand(MCOperand::CreateImm(0));
1436 return;
1437 }
1438
1439 // Otherwise, it's a normal memory reg+offset.
Jim Grosbach871dff72011-10-11 15:59:20 +00001440 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1441 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001442 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendling092a7bd2010-12-14 03:36:38 +00001443 }
Bill Wendling811c9362010-11-30 07:44:32 +00001444
Jim Grosbach05541f42011-09-19 22:21:13 +00001445 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1446 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001447 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1448 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach05541f42011-09-19 22:21:13 +00001449 }
1450
1451 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1452 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001453 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1454 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach05541f42011-09-19 22:21:13 +00001455 }
1456
Jim Grosbachd3595712011-08-03 23:50:40 +00001457 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1458 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001459 unsigned Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1460 Memory.ShiftImm, Memory.ShiftType);
1461 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1462 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001463 Inst.addOperand(MCOperand::CreateImm(Val));
1464 }
1465
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001466 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1467 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001468 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1469 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1470 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001471 }
1472
Jim Grosbachd3595712011-08-03 23:50:40 +00001473 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1474 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001475 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1476 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001477 }
1478
Jim Grosbach3fe94e32011-08-19 17:55:24 +00001479 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1480 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001481 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1482 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach3fe94e32011-08-19 17:55:24 +00001483 Inst.addOperand(MCOperand::CreateImm(Val));
1484 }
1485
Jim Grosbach26d35872011-08-19 18:55:51 +00001486 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1487 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001488 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1489 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach26d35872011-08-19 18:55:51 +00001490 Inst.addOperand(MCOperand::CreateImm(Val));
1491 }
1492
Jim Grosbacha32c7532011-08-19 18:49:59 +00001493 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1494 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001495 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1496 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha32c7532011-08-19 18:49:59 +00001497 Inst.addOperand(MCOperand::CreateImm(Val));
1498 }
1499
Jim Grosbach23983d62011-08-19 18:13:48 +00001500 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1501 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001502 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1503 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach23983d62011-08-19 18:13:48 +00001504 Inst.addOperand(MCOperand::CreateImm(Val));
1505 }
1506
Jim Grosbachd3595712011-08-03 23:50:40 +00001507 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1508 assert(N == 1 && "Invalid number of operands!");
1509 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1510 assert(CE && "non-constant post-idx-imm8 operand!");
1511 int Imm = CE->getValue();
1512 bool isAdd = Imm >= 0;
Owen Andersonf02d98d2011-08-29 17:17:09 +00001513 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00001514 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1515 Inst.addOperand(MCOperand::CreateImm(Imm));
1516 }
1517
Jim Grosbach93981412011-10-11 21:55:36 +00001518 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1519 assert(N == 1 && "Invalid number of operands!");
1520 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1521 assert(CE && "non-constant post-idx-imm8s4 operand!");
1522 int Imm = CE->getValue();
1523 bool isAdd = Imm >= 0;
1524 if (Imm == INT32_MIN) Imm = 0;
1525 // Immediate is scaled by 4.
1526 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1527 Inst.addOperand(MCOperand::CreateImm(Imm));
1528 }
1529
Jim Grosbachd3595712011-08-03 23:50:40 +00001530 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1531 assert(N == 2 && "Invalid number of operands!");
1532 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachc320c852011-08-05 21:28:30 +00001533 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1534 }
1535
1536 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1537 assert(N == 2 && "Invalid number of operands!");
1538 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1539 // The sign, shift type, and shift amount are encoded in a single operand
1540 // using the AM2 encoding helpers.
1541 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1542 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1543 PostIdxReg.ShiftTy);
1544 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendling811c9362010-11-30 07:44:32 +00001545 }
1546
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001547 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1548 assert(N == 1 && "Invalid number of operands!");
1549 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1550 }
1551
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001552 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1553 assert(N == 1 && "Invalid number of operands!");
1554 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1555 }
1556
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001557 void addVecListOneDOperands(MCInst &Inst, unsigned N) const {
1558 assert(N == 1 && "Invalid number of operands!");
1559 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1560 }
1561
Jim Grosbach2f2e3c42011-10-21 18:54:25 +00001562 void addVecListTwoDOperands(MCInst &Inst, unsigned N) const {
1563 assert(N == 1 && "Invalid number of operands!");
1564 // Only the first register actually goes on the instruction. The rest
1565 // are implied by the opcode.
1566 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1567 }
1568
Jim Grosbachc4360fe2011-10-21 20:02:19 +00001569 void addVecListThreeDOperands(MCInst &Inst, unsigned N) const {
1570 assert(N == 1 && "Invalid number of operands!");
1571 // Only the first register actually goes on the instruction. The rest
1572 // are implied by the opcode.
1573 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1574 }
1575
Jim Grosbach846bcff2011-10-21 20:35:01 +00001576 void addVecListFourDOperands(MCInst &Inst, unsigned N) const {
1577 assert(N == 1 && "Invalid number of operands!");
1578 // Only the first register actually goes on the instruction. The rest
1579 // are implied by the opcode.
1580 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1581 }
1582
Jim Grosbach118b38c2011-10-21 22:21:10 +00001583 void addVecListTwoQOperands(MCInst &Inst, unsigned N) const {
1584 assert(N == 1 && "Invalid number of operands!");
1585 // Only the first register actually goes on the instruction. The rest
1586 // are implied by the opcode.
1587 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1588 }
1589
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001590 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1591 assert(N == 1 && "Invalid number of operands!");
1592 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1593 }
1594
1595 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1596 assert(N == 1 && "Invalid number of operands!");
1597 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1598 }
1599
1600 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1601 assert(N == 1 && "Invalid number of operands!");
1602 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1603 }
1604
Jim Grosbach741cd732011-10-17 22:26:03 +00001605 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1606 assert(N == 1 && "Invalid number of operands!");
1607 // The immediate encodes the type of constant as well as the value.
1608 // Mask in that this is an i8 splat.
1609 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1610 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1611 }
1612
Jim Grosbachcda32ae2011-10-17 23:09:09 +00001613 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1614 assert(N == 1 && "Invalid number of operands!");
1615 // The immediate encodes the type of constant as well as the value.
1616 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1617 unsigned Value = CE->getValue();
1618 if (Value >= 256)
1619 Value = (Value >> 8) | 0xa00;
1620 else
1621 Value |= 0x800;
1622 Inst.addOperand(MCOperand::CreateImm(Value));
1623 }
1624
Jim Grosbach8211c052011-10-18 00:22:00 +00001625 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1626 assert(N == 1 && "Invalid number of operands!");
1627 // The immediate encodes the type of constant as well as the value.
1628 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1629 unsigned Value = CE->getValue();
1630 if (Value >= 256 && Value <= 0xff00)
1631 Value = (Value >> 8) | 0x200;
1632 else if (Value > 0xffff && Value <= 0xff0000)
1633 Value = (Value >> 16) | 0x400;
1634 else if (Value > 0xffffff)
1635 Value = (Value >> 24) | 0x600;
1636 Inst.addOperand(MCOperand::CreateImm(Value));
1637 }
1638
1639 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1640 assert(N == 1 && "Invalid number of operands!");
1641 // The immediate encodes the type of constant as well as the value.
1642 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1643 unsigned Value = CE->getValue();
1644 if (Value >= 256 && Value <= 0xffff)
1645 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1646 else if (Value > 0xffff && Value <= 0xffffff)
1647 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1648 else if (Value > 0xffffff)
1649 Value = (Value >> 24) | 0x600;
1650 Inst.addOperand(MCOperand::CreateImm(Value));
1651 }
1652
Jim Grosbache4454e02011-10-18 16:18:11 +00001653 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1654 assert(N == 1 && "Invalid number of operands!");
1655 // The immediate encodes the type of constant as well as the value.
1656 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1657 uint64_t Value = CE->getValue();
1658 unsigned Imm = 0;
1659 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1660 Imm |= (Value & 1) << i;
1661 }
1662 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1663 }
1664
Jim Grosbach602aa902011-07-13 15:34:57 +00001665 virtual void print(raw_ostream &OS) const;
Daniel Dunbarebace222010-08-11 06:37:04 +00001666
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001667 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001668 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001669 Op->ITMask.Mask = Mask;
1670 Op->StartLoc = S;
1671 Op->EndLoc = S;
1672 return Op;
1673 }
1674
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001675 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001676 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001677 Op->CC.Val = CC;
1678 Op->StartLoc = S;
1679 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001680 return Op;
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001681 }
1682
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001683 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001684 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001685 Op->Cop.Val = CopVal;
1686 Op->StartLoc = S;
1687 Op->EndLoc = S;
1688 return Op;
1689 }
1690
1691 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001692 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001693 Op->Cop.Val = CopVal;
1694 Op->StartLoc = S;
1695 Op->EndLoc = S;
1696 return Op;
1697 }
1698
Jim Grosbach48399582011-10-12 17:34:41 +00001699 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1700 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1701 Op->Cop.Val = Val;
1702 Op->StartLoc = S;
1703 Op->EndLoc = E;
1704 return Op;
1705 }
1706
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001707 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001708 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001709 Op->Reg.RegNum = RegNum;
1710 Op->StartLoc = S;
1711 Op->EndLoc = S;
1712 return Op;
1713 }
1714
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001715 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001716 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001717 Op->Tok.Data = Str.data();
1718 Op->Tok.Length = Str.size();
1719 Op->StartLoc = S;
1720 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001721 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001722 }
1723
Bill Wendling2063b842010-11-18 23:43:05 +00001724 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001725 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001726 Op->Reg.RegNum = RegNum;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001727 Op->StartLoc = S;
1728 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001729 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001730 }
1731
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001732 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1733 unsigned SrcReg,
1734 unsigned ShiftReg,
1735 unsigned ShiftImm,
1736 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001737 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachac798e12011-07-25 20:49:51 +00001738 Op->RegShiftedReg.ShiftTy = ShTy;
1739 Op->RegShiftedReg.SrcReg = SrcReg;
1740 Op->RegShiftedReg.ShiftReg = ShiftReg;
1741 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001742 Op->StartLoc = S;
1743 Op->EndLoc = E;
1744 return Op;
1745 }
1746
Owen Andersonb595ed02011-07-21 18:54:16 +00001747 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1748 unsigned SrcReg,
1749 unsigned ShiftImm,
1750 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001751 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachac798e12011-07-25 20:49:51 +00001752 Op->RegShiftedImm.ShiftTy = ShTy;
1753 Op->RegShiftedImm.SrcReg = SrcReg;
1754 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Andersonb595ed02011-07-21 18:54:16 +00001755 Op->StartLoc = S;
1756 Op->EndLoc = E;
1757 return Op;
1758 }
1759
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001760 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001761 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001762 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001763 Op->ShifterImm.isASR = isASR;
1764 Op->ShifterImm.Imm = Imm;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001765 Op->StartLoc = S;
1766 Op->EndLoc = E;
1767 return Op;
1768 }
1769
Jim Grosbach833b9d32011-07-27 20:15:40 +00001770 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001771 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach833b9d32011-07-27 20:15:40 +00001772 Op->RotImm.Imm = Imm;
1773 Op->StartLoc = S;
1774 Op->EndLoc = E;
1775 return Op;
1776 }
1777
Jim Grosbach864b6092011-07-28 21:34:26 +00001778 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1779 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001780 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach864b6092011-07-28 21:34:26 +00001781 Op->Bitfield.LSB = LSB;
1782 Op->Bitfield.Width = Width;
1783 Op->StartLoc = S;
1784 Op->EndLoc = E;
1785 return Op;
1786 }
1787
Bill Wendling2cae3272010-11-09 22:44:22 +00001788 static ARMOperand *
Bill Wendlingbed94652010-11-09 23:28:44 +00001789 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00001790 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001791 KindTy Kind = k_RegisterList;
Bill Wendling9898ac92010-11-17 04:32:08 +00001792
Jim Grosbach75461af2011-09-13 22:56:44 +00001793 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001794 Kind = k_DPRRegisterList;
Jim Grosbach75461af2011-09-13 22:56:44 +00001795 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng9eec7642011-07-25 21:32:49 +00001796 contains(Regs.front().first))
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001797 Kind = k_SPRRegisterList;
Bill Wendling9898ac92010-11-17 04:32:08 +00001798
1799 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendlingbed94652010-11-09 23:28:44 +00001800 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00001801 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling0ab0f672010-11-18 21:50:54 +00001802 Op->Registers.push_back(I->first);
Bill Wendling20b5ea982010-11-19 00:38:19 +00001803 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00001804 Op->StartLoc = StartLoc;
1805 Op->EndLoc = EndLoc;
Bill Wendling7cef4472010-11-06 19:56:04 +00001806 return Op;
1807 }
1808
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001809 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
1810 SMLoc S, SMLoc E) {
1811 ARMOperand *Op = new ARMOperand(k_VectorList);
1812 Op->VectorList.RegNum = RegNum;
1813 Op->VectorList.Count = Count;
1814 Op->StartLoc = S;
1815 Op->EndLoc = E;
1816 return Op;
1817 }
1818
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001819 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
1820 MCContext &Ctx) {
1821 ARMOperand *Op = new ARMOperand(k_VectorIndex);
1822 Op->VectorIndex.Val = Idx;
1823 Op->StartLoc = S;
1824 Op->EndLoc = E;
1825 return Op;
1826 }
1827
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001828 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001829 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001830 Op->Imm.Val = Val;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001831 Op->StartLoc = S;
1832 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001833 return Op;
Kevin Enderbyf5079942009-10-13 22:19:02 +00001834 }
1835
Jim Grosbache7fbce72011-10-03 23:38:36 +00001836 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001837 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbache7fbce72011-10-03 23:38:36 +00001838 Op->FPImm.Val = Val;
1839 Op->StartLoc = S;
1840 Op->EndLoc = S;
1841 return Op;
1842 }
1843
Jim Grosbachd3595712011-08-03 23:50:40 +00001844 static ARMOperand *CreateMem(unsigned BaseRegNum,
1845 const MCConstantExpr *OffsetImm,
1846 unsigned OffsetRegNum,
1847 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00001848 unsigned ShiftImm,
Jim Grosbacha95ec992011-10-11 17:29:55 +00001849 unsigned Alignment,
Jim Grosbachd3595712011-08-03 23:50:40 +00001850 bool isNegative,
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001851 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001852 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbach871dff72011-10-11 15:59:20 +00001853 Op->Memory.BaseRegNum = BaseRegNum;
1854 Op->Memory.OffsetImm = OffsetImm;
1855 Op->Memory.OffsetRegNum = OffsetRegNum;
1856 Op->Memory.ShiftType = ShiftType;
1857 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbacha95ec992011-10-11 17:29:55 +00001858 Op->Memory.Alignment = Alignment;
Jim Grosbach871dff72011-10-11 15:59:20 +00001859 Op->Memory.isNegative = isNegative;
Jim Grosbachd3595712011-08-03 23:50:40 +00001860 Op->StartLoc = S;
1861 Op->EndLoc = E;
1862 return Op;
1863 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00001864
Jim Grosbachc320c852011-08-05 21:28:30 +00001865 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
1866 ARM_AM::ShiftOpc ShiftTy,
1867 unsigned ShiftImm,
Jim Grosbachd3595712011-08-03 23:50:40 +00001868 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001869 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbachd3595712011-08-03 23:50:40 +00001870 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachc320c852011-08-05 21:28:30 +00001871 Op->PostIdxReg.isAdd = isAdd;
1872 Op->PostIdxReg.ShiftTy = ShiftTy;
1873 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001874 Op->StartLoc = S;
1875 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001876 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001877 }
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001878
1879 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001880 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001881 Op->MBOpt.Val = Opt;
1882 Op->StartLoc = S;
1883 Op->EndLoc = S;
1884 return Op;
1885 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001886
1887 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001888 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001889 Op->IFlags.Val = IFlags;
1890 Op->StartLoc = S;
1891 Op->EndLoc = S;
1892 return Op;
1893 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001894
1895 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001896 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001897 Op->MMask.Val = MMask;
1898 Op->StartLoc = S;
1899 Op->EndLoc = S;
1900 return Op;
1901 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001902};
1903
1904} // end anonymous namespace.
1905
Jim Grosbach602aa902011-07-13 15:34:57 +00001906void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001907 switch (Kind) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001908 case k_FPImmediate:
Jim Grosbache7fbce72011-10-03 23:38:36 +00001909 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
1910 << ") >";
1911 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001912 case k_CondCode:
Daniel Dunbar2be732a2011-01-10 15:26:21 +00001913 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001914 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001915 case k_CCOut:
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001916 OS << "<ccout " << getReg() << ">";
1917 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001918 case k_ITCondMask: {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00001919 static const char *MaskStr[] = {
1920 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
1921 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
1922 };
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001923 assert((ITMask.Mask & 0xf) == ITMask.Mask);
1924 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
1925 break;
1926 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001927 case k_CoprocNum:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001928 OS << "<coprocessor number: " << getCoproc() << ">";
1929 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001930 case k_CoprocReg:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001931 OS << "<coprocessor register: " << getCoproc() << ">";
1932 break;
Jim Grosbach48399582011-10-12 17:34:41 +00001933 case k_CoprocOption:
1934 OS << "<coprocessor option: " << CoprocOption.Val << ">";
1935 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001936 case k_MSRMask:
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001937 OS << "<mask: " << getMSRMask() << ">";
1938 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001939 case k_Immediate:
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001940 getImm()->print(OS);
1941 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001942 case k_MemBarrierOpt:
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001943 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
1944 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001945 case k_Memory:
Daniel Dunbarbcd8eb02011-01-18 05:55:21 +00001946 OS << "<memory "
Jim Grosbach871dff72011-10-11 15:59:20 +00001947 << " base:" << Memory.BaseRegNum;
Daniel Dunbarbcd8eb02011-01-18 05:55:21 +00001948 OS << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001949 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001950 case k_PostIndexRegister:
Jim Grosbachc320c852011-08-05 21:28:30 +00001951 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
1952 << PostIdxReg.RegNum;
1953 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
1954 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
1955 << PostIdxReg.ShiftImm;
1956 OS << ">";
Jim Grosbachd3595712011-08-03 23:50:40 +00001957 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001958 case k_ProcIFlags: {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001959 OS << "<ARM_PROC::";
1960 unsigned IFlags = getProcIFlags();
1961 for (int i=2; i >= 0; --i)
1962 if (IFlags & (1 << i))
1963 OS << ARM_PROC::IFlagsToString(1 << i);
1964 OS << ">";
1965 break;
1966 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001967 case k_Register:
Bill Wendling2063b842010-11-18 23:43:05 +00001968 OS << "<register " << getReg() << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001969 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001970 case k_ShifterImmediate:
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001971 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
1972 << " #" << ShifterImm.Imm << ">";
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001973 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001974 case k_ShiftedRegister:
Owen Andersonb595ed02011-07-21 18:54:16 +00001975 OS << "<so_reg_reg "
Jim Grosbachac798e12011-07-25 20:49:51 +00001976 << RegShiftedReg.SrcReg
1977 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedReg.ShiftImm))
1978 << ", " << RegShiftedReg.ShiftReg << ", "
1979 << ARM_AM::getSORegOffset(RegShiftedReg.ShiftImm)
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001980 << ">";
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001981 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001982 case k_ShiftedImmediate:
Owen Andersonb595ed02011-07-21 18:54:16 +00001983 OS << "<so_reg_imm "
Jim Grosbachac798e12011-07-25 20:49:51 +00001984 << RegShiftedImm.SrcReg
1985 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedImm.ShiftImm))
1986 << ", " << ARM_AM::getSORegOffset(RegShiftedImm.ShiftImm)
Owen Andersonb595ed02011-07-21 18:54:16 +00001987 << ">";
1988 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001989 case k_RotateImmediate:
Jim Grosbach833b9d32011-07-27 20:15:40 +00001990 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
1991 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001992 case k_BitfieldDescriptor:
Jim Grosbach864b6092011-07-28 21:34:26 +00001993 OS << "<bitfield " << "lsb: " << Bitfield.LSB
1994 << ", width: " << Bitfield.Width << ">";
1995 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001996 case k_RegisterList:
1997 case k_DPRRegisterList:
1998 case k_SPRRegisterList: {
Bill Wendling7cef4472010-11-06 19:56:04 +00001999 OS << "<register_list ";
Bill Wendling7cef4472010-11-06 19:56:04 +00002000
Bill Wendlingbed94652010-11-09 23:28:44 +00002001 const SmallVectorImpl<unsigned> &RegList = getRegList();
2002 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00002003 I = RegList.begin(), E = RegList.end(); I != E; ) {
2004 OS << *I;
2005 if (++I < E) OS << ", ";
Bill Wendling7cef4472010-11-06 19:56:04 +00002006 }
2007
2008 OS << ">";
2009 break;
2010 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002011 case k_VectorList:
2012 OS << "<vector_list " << VectorList.Count << " * "
2013 << VectorList.RegNum << ">";
2014 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002015 case k_Token:
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002016 OS << "'" << getToken() << "'";
2017 break;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002018 case k_VectorIndex:
2019 OS << "<vectorindex " << getVectorIndex() << ">";
2020 break;
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002021 }
2022}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00002023
2024/// @name Auto-generated Match Functions
2025/// {
2026
2027static unsigned MatchRegisterName(StringRef Name);
2028
2029/// }
2030
Bob Wilsonfb0bd042011-02-03 21:46:10 +00002031bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2032 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002033 RegNo = tryParseRegister();
Roman Divacky36b1b472011-01-27 17:14:22 +00002034
2035 return (RegNo == (unsigned)-1);
2036}
2037
Kevin Enderby8be42bd2009-10-30 22:55:57 +00002038/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattner44e5981c2010-10-30 04:09:10 +00002039/// and if it is a register name the token is eaten and the register number is
2040/// returned. Otherwise return -1.
2041///
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002042int ARMAsmParser::tryParseRegister() {
Chris Lattner44e5981c2010-10-30 04:09:10 +00002043 const AsmToken &Tok = Parser.getTok();
Jim Grosbachd3595712011-08-03 23:50:40 +00002044 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbach99710a82010-11-01 16:44:21 +00002045
Chris Lattner44e5981c2010-10-30 04:09:10 +00002046 // FIXME: Validate register for the current architecture; we have to do
2047 // validation later, so maybe there is no need for this here.
Owen Andersona098d152011-01-13 22:50:36 +00002048 std::string upperCase = Tok.getString().str();
2049 std::string lowerCase = LowercaseString(upperCase);
2050 unsigned RegNum = MatchRegisterName(lowerCase);
2051 if (!RegNum) {
2052 RegNum = StringSwitch<unsigned>(lowerCase)
2053 .Case("r13", ARM::SP)
2054 .Case("r14", ARM::LR)
2055 .Case("r15", ARM::PC)
2056 .Case("ip", ARM::R12)
2057 .Default(0);
2058 }
2059 if (!RegNum) return -1;
Bob Wilsonfb0bd042011-02-03 21:46:10 +00002060
Chris Lattner44e5981c2010-10-30 04:09:10 +00002061 Parser.Lex(); // Eat identifier token.
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002062
Chris Lattner44e5981c2010-10-30 04:09:10 +00002063 return RegNum;
2064}
Jim Grosbach99710a82010-11-01 16:44:21 +00002065
Jim Grosbachbb24c592011-07-13 18:49:30 +00002066// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2067// If a recoverable error occurs, return 1. If an irrecoverable error
2068// occurs, return -1. An irrecoverable error is one where tokens have been
2069// consumed in the process of trying to parse the shifter (i.e., when it is
2070// indeed a shifter operand, but malformed).
Jim Grosbach0d6022d2011-07-26 20:41:24 +00002071int ARMAsmParser::tryParseShiftRegister(
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002072 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2073 SMLoc S = Parser.getTok().getLoc();
2074 const AsmToken &Tok = Parser.getTok();
2075 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2076
2077 std::string upperCase = Tok.getString().str();
2078 std::string lowerCase = LowercaseString(upperCase);
2079 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
2080 .Case("lsl", ARM_AM::lsl)
2081 .Case("lsr", ARM_AM::lsr)
2082 .Case("asr", ARM_AM::asr)
2083 .Case("ror", ARM_AM::ror)
2084 .Case("rrx", ARM_AM::rrx)
2085 .Default(ARM_AM::no_shift);
2086
2087 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbachbb24c592011-07-13 18:49:30 +00002088 return 1;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002089
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002090 Parser.Lex(); // Eat the operator.
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002091
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002092 // The source register for the shift has already been added to the
2093 // operand list, so we need to pop it off and combine it into the shifted
2094 // register operand instead.
Benjamin Kramer1757e7a2011-07-14 18:41:22 +00002095 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002096 if (!PrevOp->isReg())
2097 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2098 int SrcReg = PrevOp->getReg();
2099 int64_t Imm = 0;
2100 int ShiftReg = 0;
2101 if (ShiftTy == ARM_AM::rrx) {
2102 // RRX Doesn't have an explicit shift amount. The encoder expects
2103 // the shift register to be the same as the source register. Seems odd,
2104 // but OK.
2105 ShiftReg = SrcReg;
2106 } else {
2107 // Figure out if this is shifted by a constant or a register (for non-RRX).
2108 if (Parser.getTok().is(AsmToken::Hash)) {
2109 Parser.Lex(); // Eat hash.
2110 SMLoc ImmLoc = Parser.getTok().getLoc();
2111 const MCExpr *ShiftExpr = 0;
Jim Grosbachbb24c592011-07-13 18:49:30 +00002112 if (getParser().ParseExpression(ShiftExpr)) {
2113 Error(ImmLoc, "invalid immediate shift value");
2114 return -1;
2115 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002116 // The expression must be evaluatable as an immediate.
2117 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbachbb24c592011-07-13 18:49:30 +00002118 if (!CE) {
2119 Error(ImmLoc, "invalid immediate shift value");
2120 return -1;
2121 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002122 // Range check the immediate.
2123 // lsl, ror: 0 <= imm <= 31
2124 // lsr, asr: 0 <= imm <= 32
2125 Imm = CE->getValue();
2126 if (Imm < 0 ||
2127 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2128 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbachbb24c592011-07-13 18:49:30 +00002129 Error(ImmLoc, "immediate shift value out of range");
2130 return -1;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002131 }
2132 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002133 ShiftReg = tryParseRegister();
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002134 SMLoc L = Parser.getTok().getLoc();
Jim Grosbachbb24c592011-07-13 18:49:30 +00002135 if (ShiftReg == -1) {
2136 Error (L, "expected immediate or register in shift operand");
2137 return -1;
2138 }
2139 } else {
2140 Error (Parser.getTok().getLoc(),
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002141 "expected immediate or register in shift operand");
Jim Grosbachbb24c592011-07-13 18:49:30 +00002142 return -1;
2143 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002144 }
2145
Owen Andersonb595ed02011-07-21 18:54:16 +00002146 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2147 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachac798e12011-07-25 20:49:51 +00002148 ShiftReg, Imm,
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002149 S, Parser.getTok().getLoc()));
Owen Andersonb595ed02011-07-21 18:54:16 +00002150 else
2151 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2152 S, Parser.getTok().getLoc()));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002153
Jim Grosbachbb24c592011-07-13 18:49:30 +00002154 return 0;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002155}
2156
2157
Bill Wendling2063b842010-11-18 23:43:05 +00002158/// Try to parse a register name. The token must be an Identifier when called.
2159/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2160/// if there is a "writeback". 'true' if it's not a register.
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002161///
Kevin Enderby8be42bd2009-10-30 22:55:57 +00002162/// TODO this is likely to change to allow different register types and or to
2163/// parse for a specific register type.
Bill Wendling2063b842010-11-18 23:43:05 +00002164bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002165tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattner44e5981c2010-10-30 04:09:10 +00002166 SMLoc S = Parser.getTok().getLoc();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002167 int RegNo = tryParseRegister();
Bill Wendlinge18980a2010-11-06 22:36:58 +00002168 if (RegNo == -1)
Bill Wendling2063b842010-11-18 23:43:05 +00002169 return true;
Jim Grosbach99710a82010-11-01 16:44:21 +00002170
Bill Wendling2063b842010-11-18 23:43:05 +00002171 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002172
Chris Lattner44e5981c2010-10-30 04:09:10 +00002173 const AsmToken &ExclaimTok = Parser.getTok();
2174 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling2063b842010-11-18 23:43:05 +00002175 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2176 ExclaimTok.getLoc()));
Chris Lattner44e5981c2010-10-30 04:09:10 +00002177 Parser.Lex(); // Eat exclaim token
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002178 return false;
2179 }
2180
2181 // Also check for an index operand. This is only legal for vector registers,
2182 // but that'll get caught OK in operand matching, so we don't need to
2183 // explicitly filter everything else out here.
2184 if (Parser.getTok().is(AsmToken::LBrac)) {
2185 SMLoc SIdx = Parser.getTok().getLoc();
2186 Parser.Lex(); // Eat left bracket token.
2187
2188 const MCExpr *ImmVal;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002189 if (getParser().ParseExpression(ImmVal))
2190 return MatchOperand_ParseFail;
2191 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2192 if (!MCE) {
2193 TokError("immediate value expected for vector index");
2194 return MatchOperand_ParseFail;
2195 }
2196
2197 SMLoc E = Parser.getTok().getLoc();
2198 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2199 Error(E, "']' expected");
2200 return MatchOperand_ParseFail;
2201 }
2202
2203 Parser.Lex(); // Eat right bracket token.
2204
2205 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2206 SIdx, E,
2207 getContext()));
Kevin Enderby2207e5f2009-10-07 18:01:35 +00002208 }
2209
Bill Wendling2063b842010-11-18 23:43:05 +00002210 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002211}
2212
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002213/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2214/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2215/// "c5", ...
2216static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002217 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2218 // but efficient.
2219 switch (Name.size()) {
2220 default: break;
2221 case 2:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002222 if (Name[0] != CoprocOp)
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002223 return -1;
2224 switch (Name[1]) {
2225 default: return -1;
2226 case '0': return 0;
2227 case '1': return 1;
2228 case '2': return 2;
2229 case '3': return 3;
2230 case '4': return 4;
2231 case '5': return 5;
2232 case '6': return 6;
2233 case '7': return 7;
2234 case '8': return 8;
2235 case '9': return 9;
2236 }
2237 break;
2238 case 3:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002239 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002240 return -1;
2241 switch (Name[2]) {
2242 default: return -1;
2243 case '0': return 10;
2244 case '1': return 11;
2245 case '2': return 12;
2246 case '3': return 13;
2247 case '4': return 14;
2248 case '5': return 15;
2249 }
2250 break;
2251 }
2252
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002253 return -1;
2254}
2255
Jim Grosbach3d1eac82011-08-26 21:43:41 +00002256/// parseITCondCode - Try to parse a condition code for an IT instruction.
2257ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2258parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2259 SMLoc S = Parser.getTok().getLoc();
2260 const AsmToken &Tok = Parser.getTok();
2261 if (!Tok.is(AsmToken::Identifier))
2262 return MatchOperand_NoMatch;
2263 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2264 .Case("eq", ARMCC::EQ)
2265 .Case("ne", ARMCC::NE)
2266 .Case("hs", ARMCC::HS)
2267 .Case("cs", ARMCC::HS)
2268 .Case("lo", ARMCC::LO)
2269 .Case("cc", ARMCC::LO)
2270 .Case("mi", ARMCC::MI)
2271 .Case("pl", ARMCC::PL)
2272 .Case("vs", ARMCC::VS)
2273 .Case("vc", ARMCC::VC)
2274 .Case("hi", ARMCC::HI)
2275 .Case("ls", ARMCC::LS)
2276 .Case("ge", ARMCC::GE)
2277 .Case("lt", ARMCC::LT)
2278 .Case("gt", ARMCC::GT)
2279 .Case("le", ARMCC::LE)
2280 .Case("al", ARMCC::AL)
2281 .Default(~0U);
2282 if (CC == ~0U)
2283 return MatchOperand_NoMatch;
2284 Parser.Lex(); // Eat the token.
2285
2286 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2287
2288 return MatchOperand_Success;
2289}
2290
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002291/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002292/// token must be an Identifier when called, and if it is a coprocessor
2293/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002294ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002295parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002296 SMLoc S = Parser.getTok().getLoc();
2297 const AsmToken &Tok = Parser.getTok();
Jim Grosbach54a20ed2011-10-12 20:54:17 +00002298 if (Tok.isNot(AsmToken::Identifier))
2299 return MatchOperand_NoMatch;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002300
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002301 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002302 if (Num == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002303 return MatchOperand_NoMatch;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002304
2305 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002306 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002307 return MatchOperand_Success;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002308}
2309
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002310/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002311/// token must be an Identifier when called, and if it is a coprocessor
2312/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002313ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002314parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002315 SMLoc S = Parser.getTok().getLoc();
2316 const AsmToken &Tok = Parser.getTok();
Jim Grosbach54a20ed2011-10-12 20:54:17 +00002317 if (Tok.isNot(AsmToken::Identifier))
2318 return MatchOperand_NoMatch;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002319
2320 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2321 if (Reg == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002322 return MatchOperand_NoMatch;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002323
2324 Parser.Lex(); // Eat identifier token.
2325 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002326 return MatchOperand_Success;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002327}
2328
Jim Grosbach48399582011-10-12 17:34:41 +00002329/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2330/// coproc_option : '{' imm0_255 '}'
2331ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2332parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2333 SMLoc S = Parser.getTok().getLoc();
2334
2335 // If this isn't a '{', this isn't a coprocessor immediate operand.
2336 if (Parser.getTok().isNot(AsmToken::LCurly))
2337 return MatchOperand_NoMatch;
2338 Parser.Lex(); // Eat the '{'
2339
2340 const MCExpr *Expr;
2341 SMLoc Loc = Parser.getTok().getLoc();
2342 if (getParser().ParseExpression(Expr)) {
2343 Error(Loc, "illegal expression");
2344 return MatchOperand_ParseFail;
2345 }
2346 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2347 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2348 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2349 return MatchOperand_ParseFail;
2350 }
2351 int Val = CE->getValue();
2352
2353 // Check for and consume the closing '}'
2354 if (Parser.getTok().isNot(AsmToken::RCurly))
2355 return MatchOperand_ParseFail;
2356 SMLoc E = Parser.getTok().getLoc();
2357 Parser.Lex(); // Eat the '}'
2358
2359 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2360 return MatchOperand_Success;
2361}
2362
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002363// For register list parsing, we need to map from raw GPR register numbering
2364// to the enumeration values. The enumeration values aren't sorted by
2365// register number due to our using "sp", "lr" and "pc" as canonical names.
2366static unsigned getNextRegister(unsigned Reg) {
2367 // If this is a GPR, we need to do it manually, otherwise we can rely
2368 // on the sort ordering of the enumeration since the other reg-classes
2369 // are sane.
2370 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2371 return Reg + 1;
2372 switch(Reg) {
2373 default: assert(0 && "Invalid GPR number!");
2374 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2375 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2376 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2377 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2378 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2379 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2380 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2381 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2382 }
2383}
2384
2385/// Parse a register list.
Bill Wendling2063b842010-11-18 23:43:05 +00002386bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002387parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan936b0d32010-01-19 21:44:56 +00002388 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00002389 "Token is not a Left Curly Brace");
Bill Wendlinge18980a2010-11-06 22:36:58 +00002390 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002391 Parser.Lex(); // Eat '{' token.
2392 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbya2b99102009-10-09 21:12:28 +00002393
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002394 // Check the first register in the list to see what register class
2395 // this is a list of.
2396 int Reg = tryParseRegister();
2397 if (Reg == -1)
2398 return Error(RegLoc, "register expected");
2399
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00002400 const MCRegisterClass *RC;
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002401 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2402 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2403 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2404 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2405 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2406 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2407 else
2408 return Error(RegLoc, "invalid register in register list");
2409
2410 // The reglist instructions have at most 16 registers, so reserve
2411 // space for that many.
Jim Grosbache3a6a822011-09-13 20:35:57 +00002412 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002413 // Store the first register.
2414 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbya2b99102009-10-09 21:12:28 +00002415
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002416 // This starts immediately after the first register token in the list,
2417 // so we can see either a comma or a minus (range separator) as a legal
2418 // next token.
2419 while (Parser.getTok().is(AsmToken::Comma) ||
2420 Parser.getTok().is(AsmToken::Minus)) {
2421 if (Parser.getTok().is(AsmToken::Minus)) {
2422 Parser.Lex(); // Eat the comma.
2423 SMLoc EndLoc = Parser.getTok().getLoc();
2424 int EndReg = tryParseRegister();
2425 if (EndReg == -1)
2426 return Error(EndLoc, "register expected");
2427 // If the register is the same as the start reg, there's nothing
2428 // more to do.
2429 if (Reg == EndReg)
2430 continue;
2431 // The register must be in the same register class as the first.
2432 if (!RC->contains(EndReg))
2433 return Error(EndLoc, "invalid register in register list");
2434 // Ranges must go from low to high.
2435 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2436 return Error(EndLoc, "bad range in register list");
Kevin Enderbya2b99102009-10-09 21:12:28 +00002437
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002438 // Add all the registers in the range to the register list.
2439 while (Reg != EndReg) {
2440 Reg = getNextRegister(Reg);
2441 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2442 }
2443 continue;
2444 }
2445 Parser.Lex(); // Eat the comma.
2446 RegLoc = Parser.getTok().getLoc();
2447 int OldReg = Reg;
2448 Reg = tryParseRegister();
2449 if (Reg == -1)
Jim Grosbach3337e392011-09-12 23:36:42 +00002450 return Error(RegLoc, "register expected");
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002451 // The register must be in the same register class as the first.
2452 if (!RC->contains(Reg))
2453 return Error(RegLoc, "invalid register in register list");
2454 // List must be monotonically increasing.
2455 if (getARMRegisterNumbering(Reg) <= getARMRegisterNumbering(OldReg))
2456 return Error(RegLoc, "register list not in ascending order");
2457 // VFP register lists must also be contiguous.
2458 // It's OK to use the enumeration values directly here rather, as the
2459 // VFP register classes have the enum sorted properly.
2460 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2461 Reg != OldReg + 1)
2462 return Error(RegLoc, "non-contiguous register range");
2463 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Bill Wendlinge18980a2010-11-06 22:36:58 +00002464 }
2465
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002466 SMLoc E = Parser.getTok().getLoc();
2467 if (Parser.getTok().isNot(AsmToken::RCurly))
2468 return Error(E, "'}' expected");
2469 Parser.Lex(); // Eat '}' token.
2470
Bill Wendling2063b842010-11-18 23:43:05 +00002471 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2472 return false;
Kevin Enderbya2b99102009-10-09 21:12:28 +00002473}
2474
Jim Grosbach080a4992011-10-28 00:06:50 +00002475// Return the low-subreg of a given Q register.
2476static unsigned getDRegFromQReg(unsigned QReg) {
2477 switch (QReg) {
2478 default: llvm_unreachable("expected a Q register!");
2479 case ARM::Q0: return ARM::D0;
2480 case ARM::Q1: return ARM::D2;
2481 case ARM::Q2: return ARM::D4;
2482 case ARM::Q3: return ARM::D6;
2483 case ARM::Q4: return ARM::D8;
2484 case ARM::Q5: return ARM::D10;
2485 case ARM::Q6: return ARM::D12;
2486 case ARM::Q7: return ARM::D14;
2487 case ARM::Q8: return ARM::D16;
2488 case ARM::Q9: return ARM::D19;
2489 case ARM::Q10: return ARM::D20;
2490 case ARM::Q11: return ARM::D22;
2491 case ARM::Q12: return ARM::D24;
2492 case ARM::Q13: return ARM::D26;
2493 case ARM::Q14: return ARM::D28;
2494 case ARM::Q15: return ARM::D30;
2495 }
2496}
2497
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002498// parse a vector register list
2499ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2500parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2501 if(Parser.getTok().isNot(AsmToken::LCurly))
2502 return MatchOperand_NoMatch;
2503
2504 SMLoc S = Parser.getTok().getLoc();
2505 Parser.Lex(); // Eat '{' token.
2506 SMLoc RegLoc = Parser.getTok().getLoc();
2507
2508 int Reg = tryParseRegister();
2509 if (Reg == -1) {
2510 Error(RegLoc, "register expected");
2511 return MatchOperand_ParseFail;
2512 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002513 unsigned Count = 1;
Jim Grosbach080a4992011-10-28 00:06:50 +00002514 unsigned FirstReg = Reg;
2515 // The list is of D registers, but we also allow Q regs and just interpret
2516 // them as the two D sub-registers.
2517 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2518 FirstReg = Reg = getDRegFromQReg(Reg);
2519 ++Reg;
2520 ++Count;
2521 }
2522
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002523 while (Parser.getTok().is(AsmToken::Comma)) {
2524 Parser.Lex(); // Eat the comma.
2525 RegLoc = Parser.getTok().getLoc();
2526 int OldReg = Reg;
2527 Reg = tryParseRegister();
2528 if (Reg == -1) {
2529 Error(RegLoc, "register expected");
2530 return MatchOperand_ParseFail;
2531 }
Jim Grosbach080a4992011-10-28 00:06:50 +00002532 // vector register lists must be contiguous.
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002533 // It's OK to use the enumeration values directly here rather, as the
2534 // VFP register classes have the enum sorted properly.
Jim Grosbach080a4992011-10-28 00:06:50 +00002535 //
2536 // The list is of D registers, but we also allow Q regs and just interpret
2537 // them as the two D sub-registers.
2538 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2539 Reg = getDRegFromQReg(Reg);
2540 if (Reg != OldReg + 1) {
2541 Error(RegLoc, "non-contiguous register range");
2542 return MatchOperand_ParseFail;
2543 }
2544 ++Reg;
2545 Count += 2;
2546 continue;
2547 }
2548 // Normal D register. Just check that it's contiguous and keep going.
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002549 if (Reg != OldReg + 1) {
2550 Error(RegLoc, "non-contiguous register range");
2551 return MatchOperand_ParseFail;
2552 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002553 ++Count;
2554 }
2555
2556 SMLoc E = Parser.getTok().getLoc();
2557 if (Parser.getTok().isNot(AsmToken::RCurly)) {
2558 Error(E, "'}' expected");
2559 return MatchOperand_ParseFail;
2560 }
2561 Parser.Lex(); // Eat '}' token.
2562
2563 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count, S, E));
2564 return MatchOperand_Success;
2565}
2566
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002567/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002568ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002569parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002570 SMLoc S = Parser.getTok().getLoc();
2571 const AsmToken &Tok = Parser.getTok();
2572 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2573 StringRef OptStr = Tok.getString();
2574
2575 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2576 .Case("sy", ARM_MB::SY)
2577 .Case("st", ARM_MB::ST)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002578 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002579 .Case("ish", ARM_MB::ISH)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002580 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002581 .Case("ishst", ARM_MB::ISHST)
2582 .Case("nsh", ARM_MB::NSH)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002583 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002584 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002585 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002586 .Case("osh", ARM_MB::OSH)
2587 .Case("oshst", ARM_MB::OSHST)
2588 .Default(~0U);
2589
2590 if (Opt == ~0U)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002591 return MatchOperand_NoMatch;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002592
2593 Parser.Lex(); // Eat identifier token.
2594 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002595 return MatchOperand_Success;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002596}
2597
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002598/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002599ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002600parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002601 SMLoc S = Parser.getTok().getLoc();
2602 const AsmToken &Tok = Parser.getTok();
2603 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2604 StringRef IFlagsStr = Tok.getString();
2605
Owen Anderson10c5b122011-10-05 17:16:40 +00002606 // An iflags string of "none" is interpreted to mean that none of the AIF
2607 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002608 unsigned IFlags = 0;
Owen Anderson10c5b122011-10-05 17:16:40 +00002609 if (IFlagsStr != "none") {
2610 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2611 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2612 .Case("a", ARM_PROC::A)
2613 .Case("i", ARM_PROC::I)
2614 .Case("f", ARM_PROC::F)
2615 .Default(~0U);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002616
Owen Anderson10c5b122011-10-05 17:16:40 +00002617 // If some specific iflag is already set, it means that some letter is
2618 // present more than once, this is not acceptable.
2619 if (Flag == ~0U || (IFlags & Flag))
2620 return MatchOperand_NoMatch;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002621
Owen Anderson10c5b122011-10-05 17:16:40 +00002622 IFlags |= Flag;
2623 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002624 }
2625
2626 Parser.Lex(); // Eat identifier token.
2627 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2628 return MatchOperand_Success;
2629}
2630
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002631/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002632ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002633parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002634 SMLoc S = Parser.getTok().getLoc();
2635 const AsmToken &Tok = Parser.getTok();
2636 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2637 StringRef Mask = Tok.getString();
2638
James Molloy21efa7d2011-09-28 14:21:38 +00002639 if (isMClass()) {
2640 // See ARMv6-M 10.1.1
2641 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2642 .Case("apsr", 0)
2643 .Case("iapsr", 1)
2644 .Case("eapsr", 2)
2645 .Case("xpsr", 3)
2646 .Case("ipsr", 5)
2647 .Case("epsr", 6)
2648 .Case("iepsr", 7)
2649 .Case("msp", 8)
2650 .Case("psp", 9)
2651 .Case("primask", 16)
2652 .Case("basepri", 17)
2653 .Case("basepri_max", 18)
2654 .Case("faultmask", 19)
2655 .Case("control", 20)
2656 .Default(~0U);
2657
2658 if (FlagsVal == ~0U)
2659 return MatchOperand_NoMatch;
2660
2661 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
2662 // basepri, basepri_max and faultmask only valid for V7m.
2663 return MatchOperand_NoMatch;
2664
2665 Parser.Lex(); // Eat identifier token.
2666 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2667 return MatchOperand_Success;
2668 }
2669
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002670 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
2671 size_t Start = 0, Next = Mask.find('_');
2672 StringRef Flags = "";
Jim Grosbachd25c2cd2011-07-19 22:45:10 +00002673 std::string SpecReg = LowercaseString(Mask.slice(Start, Next));
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002674 if (Next != StringRef::npos)
2675 Flags = Mask.slice(Next+1, Mask.size());
2676
2677 // FlagsVal contains the complete mask:
2678 // 3-0: Mask
2679 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2680 unsigned FlagsVal = 0;
2681
2682 if (SpecReg == "apsr") {
2683 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachd25c2cd2011-07-19 22:45:10 +00002684 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002685 .Case("g", 0x4) // same as CPSR_s
2686 .Case("nzcvqg", 0xc) // same as CPSR_fs
2687 .Default(~0U);
2688
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00002689 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002690 if (!Flags.empty())
2691 return MatchOperand_NoMatch;
2692 else
Jim Grosbach0ecd3952011-09-14 20:03:46 +00002693 FlagsVal = 8; // No flag
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00002694 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002695 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes54452132011-05-25 00:35:03 +00002696 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
2697 Flags = "fc";
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002698 for (int i = 0, e = Flags.size(); i != e; ++i) {
2699 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
2700 .Case("c", 1)
2701 .Case("x", 2)
2702 .Case("s", 4)
2703 .Case("f", 8)
2704 .Default(~0U);
2705
2706 // If some specific flag is already set, it means that some letter is
2707 // present more than once, this is not acceptable.
2708 if (FlagsVal == ~0U || (FlagsVal & Flag))
2709 return MatchOperand_NoMatch;
2710 FlagsVal |= Flag;
2711 }
2712 } else // No match for special register.
2713 return MatchOperand_NoMatch;
2714
Owen Anderson03a173e2011-10-21 18:43:28 +00002715 // Special register without flags is NOT equivalent to "fc" flags.
2716 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
2717 // two lines would enable gas compatibility at the expense of breaking
2718 // round-tripping.
2719 //
2720 // if (!FlagsVal)
2721 // FlagsVal = 0x9;
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002722
2723 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2724 if (SpecReg == "spsr")
2725 FlagsVal |= 16;
2726
2727 Parser.Lex(); // Eat identifier token.
2728 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2729 return MatchOperand_Success;
2730}
2731
Jim Grosbach27c1e252011-07-21 17:23:04 +00002732ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2733parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
2734 int Low, int High) {
2735 const AsmToken &Tok = Parser.getTok();
2736 if (Tok.isNot(AsmToken::Identifier)) {
2737 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2738 return MatchOperand_ParseFail;
2739 }
2740 StringRef ShiftName = Tok.getString();
2741 std::string LowerOp = LowercaseString(Op);
2742 std::string UpperOp = UppercaseString(Op);
2743 if (ShiftName != LowerOp && ShiftName != UpperOp) {
2744 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2745 return MatchOperand_ParseFail;
2746 }
2747 Parser.Lex(); // Eat shift type token.
2748
2749 // There must be a '#' and a shift amount.
2750 if (Parser.getTok().isNot(AsmToken::Hash)) {
2751 Error(Parser.getTok().getLoc(), "'#' expected");
2752 return MatchOperand_ParseFail;
2753 }
2754 Parser.Lex(); // Eat hash token.
2755
2756 const MCExpr *ShiftAmount;
2757 SMLoc Loc = Parser.getTok().getLoc();
2758 if (getParser().ParseExpression(ShiftAmount)) {
2759 Error(Loc, "illegal expression");
2760 return MatchOperand_ParseFail;
2761 }
2762 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2763 if (!CE) {
2764 Error(Loc, "constant expression expected");
2765 return MatchOperand_ParseFail;
2766 }
2767 int Val = CE->getValue();
2768 if (Val < Low || Val > High) {
2769 Error(Loc, "immediate value out of range");
2770 return MatchOperand_ParseFail;
2771 }
2772
2773 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
2774
2775 return MatchOperand_Success;
2776}
2777
Jim Grosbach0a547702011-07-22 17:44:50 +00002778ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2779parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2780 const AsmToken &Tok = Parser.getTok();
2781 SMLoc S = Tok.getLoc();
2782 if (Tok.isNot(AsmToken::Identifier)) {
2783 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2784 return MatchOperand_ParseFail;
2785 }
2786 int Val = StringSwitch<int>(Tok.getString())
2787 .Case("be", 1)
2788 .Case("le", 0)
2789 .Default(-1);
2790 Parser.Lex(); // Eat the token.
2791
2792 if (Val == -1) {
2793 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2794 return MatchOperand_ParseFail;
2795 }
2796 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
2797 getContext()),
2798 S, Parser.getTok().getLoc()));
2799 return MatchOperand_Success;
2800}
2801
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002802/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
2803/// instructions. Legal values are:
2804/// lsl #n 'n' in [0,31]
2805/// asr #n 'n' in [1,32]
2806/// n == 32 encoded as n == 0.
2807ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2808parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2809 const AsmToken &Tok = Parser.getTok();
2810 SMLoc S = Tok.getLoc();
2811 if (Tok.isNot(AsmToken::Identifier)) {
2812 Error(S, "shift operator 'asr' or 'lsl' expected");
2813 return MatchOperand_ParseFail;
2814 }
2815 StringRef ShiftName = Tok.getString();
2816 bool isASR;
2817 if (ShiftName == "lsl" || ShiftName == "LSL")
2818 isASR = false;
2819 else if (ShiftName == "asr" || ShiftName == "ASR")
2820 isASR = true;
2821 else {
2822 Error(S, "shift operator 'asr' or 'lsl' expected");
2823 return MatchOperand_ParseFail;
2824 }
2825 Parser.Lex(); // Eat the operator.
2826
2827 // A '#' and a shift amount.
2828 if (Parser.getTok().isNot(AsmToken::Hash)) {
2829 Error(Parser.getTok().getLoc(), "'#' expected");
2830 return MatchOperand_ParseFail;
2831 }
2832 Parser.Lex(); // Eat hash token.
2833
2834 const MCExpr *ShiftAmount;
2835 SMLoc E = Parser.getTok().getLoc();
2836 if (getParser().ParseExpression(ShiftAmount)) {
2837 Error(E, "malformed shift expression");
2838 return MatchOperand_ParseFail;
2839 }
2840 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2841 if (!CE) {
2842 Error(E, "shift amount must be an immediate");
2843 return MatchOperand_ParseFail;
2844 }
2845
2846 int64_t Val = CE->getValue();
2847 if (isASR) {
2848 // Shift amount must be in [1,32]
2849 if (Val < 1 || Val > 32) {
2850 Error(E, "'asr' shift amount must be in range [1,32]");
2851 return MatchOperand_ParseFail;
2852 }
Owen Andersonf01e2de2011-09-26 21:06:22 +00002853 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
2854 if (isThumb() && Val == 32) {
2855 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
2856 return MatchOperand_ParseFail;
2857 }
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002858 if (Val == 32) Val = 0;
2859 } else {
2860 // Shift amount must be in [1,32]
2861 if (Val < 0 || Val > 31) {
2862 Error(E, "'lsr' shift amount must be in range [0,31]");
2863 return MatchOperand_ParseFail;
2864 }
2865 }
2866
2867 E = Parser.getTok().getLoc();
2868 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
2869
2870 return MatchOperand_Success;
2871}
2872
Jim Grosbach833b9d32011-07-27 20:15:40 +00002873/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
2874/// of instructions. Legal values are:
2875/// ror #n 'n' in {0, 8, 16, 24}
2876ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2877parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2878 const AsmToken &Tok = Parser.getTok();
2879 SMLoc S = Tok.getLoc();
Jim Grosbach82213192011-09-19 20:29:33 +00002880 if (Tok.isNot(AsmToken::Identifier))
2881 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00002882 StringRef ShiftName = Tok.getString();
Jim Grosbach82213192011-09-19 20:29:33 +00002883 if (ShiftName != "ror" && ShiftName != "ROR")
2884 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00002885 Parser.Lex(); // Eat the operator.
2886
2887 // A '#' and a rotate amount.
2888 if (Parser.getTok().isNot(AsmToken::Hash)) {
2889 Error(Parser.getTok().getLoc(), "'#' expected");
2890 return MatchOperand_ParseFail;
2891 }
2892 Parser.Lex(); // Eat hash token.
2893
2894 const MCExpr *ShiftAmount;
2895 SMLoc E = Parser.getTok().getLoc();
2896 if (getParser().ParseExpression(ShiftAmount)) {
2897 Error(E, "malformed rotate expression");
2898 return MatchOperand_ParseFail;
2899 }
2900 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2901 if (!CE) {
2902 Error(E, "rotate amount must be an immediate");
2903 return MatchOperand_ParseFail;
2904 }
2905
2906 int64_t Val = CE->getValue();
2907 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
2908 // normally, zero is represented in asm by omitting the rotate operand
2909 // entirely.
2910 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
2911 Error(E, "'ror' rotate amount must be 8, 16, or 24");
2912 return MatchOperand_ParseFail;
2913 }
2914
2915 E = Parser.getTok().getLoc();
2916 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
2917
2918 return MatchOperand_Success;
2919}
2920
Jim Grosbach864b6092011-07-28 21:34:26 +00002921ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2922parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2923 SMLoc S = Parser.getTok().getLoc();
2924 // The bitfield descriptor is really two operands, the LSB and the width.
2925 if (Parser.getTok().isNot(AsmToken::Hash)) {
2926 Error(Parser.getTok().getLoc(), "'#' expected");
2927 return MatchOperand_ParseFail;
2928 }
2929 Parser.Lex(); // Eat hash token.
2930
2931 const MCExpr *LSBExpr;
2932 SMLoc E = Parser.getTok().getLoc();
2933 if (getParser().ParseExpression(LSBExpr)) {
2934 Error(E, "malformed immediate expression");
2935 return MatchOperand_ParseFail;
2936 }
2937 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
2938 if (!CE) {
2939 Error(E, "'lsb' operand must be an immediate");
2940 return MatchOperand_ParseFail;
2941 }
2942
2943 int64_t LSB = CE->getValue();
2944 // The LSB must be in the range [0,31]
2945 if (LSB < 0 || LSB > 31) {
2946 Error(E, "'lsb' operand must be in the range [0,31]");
2947 return MatchOperand_ParseFail;
2948 }
2949 E = Parser.getTok().getLoc();
2950
2951 // Expect another immediate operand.
2952 if (Parser.getTok().isNot(AsmToken::Comma)) {
2953 Error(Parser.getTok().getLoc(), "too few operands");
2954 return MatchOperand_ParseFail;
2955 }
2956 Parser.Lex(); // Eat hash token.
2957 if (Parser.getTok().isNot(AsmToken::Hash)) {
2958 Error(Parser.getTok().getLoc(), "'#' expected");
2959 return MatchOperand_ParseFail;
2960 }
2961 Parser.Lex(); // Eat hash token.
2962
2963 const MCExpr *WidthExpr;
2964 if (getParser().ParseExpression(WidthExpr)) {
2965 Error(E, "malformed immediate expression");
2966 return MatchOperand_ParseFail;
2967 }
2968 CE = dyn_cast<MCConstantExpr>(WidthExpr);
2969 if (!CE) {
2970 Error(E, "'width' operand must be an immediate");
2971 return MatchOperand_ParseFail;
2972 }
2973
2974 int64_t Width = CE->getValue();
2975 // The LSB must be in the range [1,32-lsb]
2976 if (Width < 1 || Width > 32 - LSB) {
2977 Error(E, "'width' operand must be in the range [1,32-lsb]");
2978 return MatchOperand_ParseFail;
2979 }
2980 E = Parser.getTok().getLoc();
2981
2982 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
2983
2984 return MatchOperand_Success;
2985}
2986
Jim Grosbachd3595712011-08-03 23:50:40 +00002987ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2988parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2989 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachc320c852011-08-05 21:28:30 +00002990 // postidx_reg := '+' register {, shift}
2991 // | '-' register {, shift}
2992 // | register {, shift}
Jim Grosbachd3595712011-08-03 23:50:40 +00002993
2994 // This method must return MatchOperand_NoMatch without consuming any tokens
2995 // in the case where there is no match, as other alternatives take other
2996 // parse methods.
2997 AsmToken Tok = Parser.getTok();
2998 SMLoc S = Tok.getLoc();
2999 bool haveEaten = false;
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00003000 bool isAdd = true;
Jim Grosbachd3595712011-08-03 23:50:40 +00003001 int Reg = -1;
3002 if (Tok.is(AsmToken::Plus)) {
3003 Parser.Lex(); // Eat the '+' token.
3004 haveEaten = true;
3005 } else if (Tok.is(AsmToken::Minus)) {
3006 Parser.Lex(); // Eat the '-' token.
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00003007 isAdd = false;
Jim Grosbachd3595712011-08-03 23:50:40 +00003008 haveEaten = true;
3009 }
3010 if (Parser.getTok().is(AsmToken::Identifier))
3011 Reg = tryParseRegister();
3012 if (Reg == -1) {
3013 if (!haveEaten)
3014 return MatchOperand_NoMatch;
3015 Error(Parser.getTok().getLoc(), "register expected");
3016 return MatchOperand_ParseFail;
3017 }
3018 SMLoc E = Parser.getTok().getLoc();
3019
Jim Grosbachc320c852011-08-05 21:28:30 +00003020 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3021 unsigned ShiftImm = 0;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00003022 if (Parser.getTok().is(AsmToken::Comma)) {
3023 Parser.Lex(); // Eat the ','.
3024 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3025 return MatchOperand_ParseFail;
3026 }
Jim Grosbachc320c852011-08-05 21:28:30 +00003027
3028 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3029 ShiftImm, S, E));
Jim Grosbachd3595712011-08-03 23:50:40 +00003030
3031 return MatchOperand_Success;
3032}
3033
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00003034ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3035parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3036 // Check for a post-index addressing register operand. Specifically:
3037 // am3offset := '+' register
3038 // | '-' register
3039 // | register
3040 // | # imm
3041 // | # + imm
3042 // | # - imm
3043
3044 // This method must return MatchOperand_NoMatch without consuming any tokens
3045 // in the case where there is no match, as other alternatives take other
3046 // parse methods.
3047 AsmToken Tok = Parser.getTok();
3048 SMLoc S = Tok.getLoc();
3049
3050 // Do immediates first, as we always parse those if we have a '#'.
3051 if (Parser.getTok().is(AsmToken::Hash)) {
3052 Parser.Lex(); // Eat the '#'.
3053 // Explicitly look for a '-', as we need to encode negative zero
3054 // differently.
3055 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3056 const MCExpr *Offset;
3057 if (getParser().ParseExpression(Offset))
3058 return MatchOperand_ParseFail;
3059 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3060 if (!CE) {
3061 Error(S, "constant expression expected");
3062 return MatchOperand_ParseFail;
3063 }
3064 SMLoc E = Tok.getLoc();
3065 // Negative zero is encoded as the flag value INT32_MIN.
3066 int32_t Val = CE->getValue();
3067 if (isNegative && Val == 0)
3068 Val = INT32_MIN;
3069
3070 Operands.push_back(
3071 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3072
3073 return MatchOperand_Success;
3074 }
3075
3076
3077 bool haveEaten = false;
3078 bool isAdd = true;
3079 int Reg = -1;
3080 if (Tok.is(AsmToken::Plus)) {
3081 Parser.Lex(); // Eat the '+' token.
3082 haveEaten = true;
3083 } else if (Tok.is(AsmToken::Minus)) {
3084 Parser.Lex(); // Eat the '-' token.
3085 isAdd = false;
3086 haveEaten = true;
3087 }
3088 if (Parser.getTok().is(AsmToken::Identifier))
3089 Reg = tryParseRegister();
3090 if (Reg == -1) {
3091 if (!haveEaten)
3092 return MatchOperand_NoMatch;
3093 Error(Parser.getTok().getLoc(), "register expected");
3094 return MatchOperand_ParseFail;
3095 }
3096 SMLoc E = Parser.getTok().getLoc();
3097
3098 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3099 0, S, E));
3100
3101 return MatchOperand_Success;
3102}
3103
Jim Grosbach7db8d692011-09-08 22:07:06 +00003104/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3105/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3106/// when they refer multiple MIOperands inside a single one.
3107bool ARMAsmParser::
3108cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3109 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3110 // Rt, Rt2
3111 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3112 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3113 // Create a writeback register dummy placeholder.
3114 Inst.addOperand(MCOperand::CreateReg(0));
3115 // addr
3116 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3117 // pred
3118 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3119 return true;
3120}
3121
3122/// cvtT2StrdPre - Convert parsed operands to MCInst.
3123/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3124/// when they refer multiple MIOperands inside a single one.
3125bool ARMAsmParser::
3126cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3127 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3128 // Create a writeback register dummy placeholder.
3129 Inst.addOperand(MCOperand::CreateReg(0));
3130 // Rt, Rt2
3131 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3132 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3133 // addr
3134 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3135 // pred
3136 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3137 return true;
3138}
3139
Jim Grosbachc086f682011-09-08 00:39:19 +00003140/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3141/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3142/// when they refer multiple MIOperands inside a single one.
3143bool ARMAsmParser::
3144cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3145 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3146 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3147
3148 // Create a writeback register dummy placeholder.
3149 Inst.addOperand(MCOperand::CreateImm(0));
3150
3151 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3152 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3153 return true;
3154}
3155
Jim Grosbach9c0b86a2011-09-16 21:55:56 +00003156/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3157/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3158/// when they refer multiple MIOperands inside a single one.
3159bool ARMAsmParser::
3160cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3161 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3162 // Create a writeback register dummy placeholder.
3163 Inst.addOperand(MCOperand::CreateImm(0));
3164 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3165 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3166 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3167 return true;
3168}
3169
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003170/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003171/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3172/// when they refer multiple MIOperands inside a single one.
3173bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003174cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003175 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3176 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3177
3178 // Create a writeback register dummy placeholder.
3179 Inst.addOperand(MCOperand::CreateImm(0));
3180
Jim Grosbachd3595712011-08-03 23:50:40 +00003181 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003182 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3183 return true;
3184}
3185
Owen Anderson16d33f32011-08-26 20:43:14 +00003186/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3187/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3188/// when they refer multiple MIOperands inside a single one.
3189bool ARMAsmParser::
3190cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3191 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3192 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3193
3194 // Create a writeback register dummy placeholder.
3195 Inst.addOperand(MCOperand::CreateImm(0));
3196
3197 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3198 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3199 return true;
3200}
3201
3202
Jim Grosbachd564bf32011-08-11 19:22:40 +00003203/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3204/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3205/// when they refer multiple MIOperands inside a single one.
3206bool ARMAsmParser::
3207cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3208 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3209 // Create a writeback register dummy placeholder.
3210 Inst.addOperand(MCOperand::CreateImm(0));
3211 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3212 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3213 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3214 return true;
3215}
3216
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003217/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003218/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3219/// when they refer multiple MIOperands inside a single one.
3220bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003221cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003222 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3223 // Create a writeback register dummy placeholder.
3224 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd564bf32011-08-11 19:22:40 +00003225 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3226 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3227 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbachd3595712011-08-03 23:50:40 +00003228 return true;
3229}
3230
Jim Grosbachd886f8c2011-08-11 21:17:22 +00003231/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3232/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3233/// when they refer multiple MIOperands inside a single one.
3234bool ARMAsmParser::
3235cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3236 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3237 // Create a writeback register dummy placeholder.
3238 Inst.addOperand(MCOperand::CreateImm(0));
3239 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3240 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3241 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3242 return true;
3243}
3244
Jim Grosbachd3595712011-08-03 23:50:40 +00003245/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3246/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3247/// when they refer multiple MIOperands inside a single one.
3248bool ARMAsmParser::
3249cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3250 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3251 // Rt
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003252 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbachd3595712011-08-03 23:50:40 +00003253 // Create a writeback register dummy placeholder.
3254 Inst.addOperand(MCOperand::CreateImm(0));
3255 // addr
3256 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3257 // offset
3258 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3259 // pred
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003260 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3261 return true;
3262}
3263
Jim Grosbachd3595712011-08-03 23:50:40 +00003264/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003265/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3266/// when they refer multiple MIOperands inside a single one.
3267bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003268cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3269 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3270 // Rt
Owen Andersonb0e68992011-07-28 17:18:57 +00003271 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003272 // Create a writeback register dummy placeholder.
3273 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd3595712011-08-03 23:50:40 +00003274 // addr
3275 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3276 // offset
3277 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3278 // pred
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003279 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3280 return true;
3281}
3282
Jim Grosbachd3595712011-08-03 23:50:40 +00003283/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003284/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3285/// when they refer multiple MIOperands inside a single one.
3286bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003287cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3288 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003289 // Create a writeback register dummy placeholder.
3290 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd3595712011-08-03 23:50:40 +00003291 // Rt
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003292 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbachd3595712011-08-03 23:50:40 +00003293 // addr
3294 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3295 // offset
3296 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3297 // pred
3298 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3299 return true;
3300}
3301
3302/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3303/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3304/// when they refer multiple MIOperands inside a single one.
3305bool ARMAsmParser::
3306cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3307 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3308 // Create a writeback register dummy placeholder.
3309 Inst.addOperand(MCOperand::CreateImm(0));
3310 // Rt
3311 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3312 // addr
3313 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3314 // offset
3315 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3316 // pred
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003317 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3318 return true;
3319}
3320
Jim Grosbach5b96b802011-08-10 20:29:19 +00003321/// cvtLdrdPre - Convert parsed operands to MCInst.
3322/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3323/// when they refer multiple MIOperands inside a single one.
3324bool ARMAsmParser::
3325cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3326 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3327 // Rt, Rt2
3328 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3329 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3330 // Create a writeback register dummy placeholder.
3331 Inst.addOperand(MCOperand::CreateImm(0));
3332 // addr
3333 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3334 // pred
3335 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3336 return true;
3337}
3338
Jim Grosbacheb09f492011-08-11 20:28:23 +00003339/// cvtStrdPre - Convert parsed operands to MCInst.
3340/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3341/// when they refer multiple MIOperands inside a single one.
3342bool ARMAsmParser::
3343cvtStrdPre(MCInst &Inst, unsigned Opcode,
3344 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3345 // Create a writeback register dummy placeholder.
3346 Inst.addOperand(MCOperand::CreateImm(0));
3347 // Rt, Rt2
3348 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3349 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3350 // addr
3351 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3352 // pred
3353 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3354 return true;
3355}
3356
Jim Grosbachcd4dd252011-08-10 22:42:16 +00003357/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3358/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3359/// when they refer multiple MIOperands inside a single one.
3360bool ARMAsmParser::
3361cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3362 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3363 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3364 // Create a writeback register dummy placeholder.
3365 Inst.addOperand(MCOperand::CreateImm(0));
3366 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3367 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3368 return true;
3369}
3370
Jim Grosbach8e048492011-08-19 22:07:46 +00003371/// cvtThumbMultiple- Convert parsed operands to MCInst.
3372/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3373/// when they refer multiple MIOperands inside a single one.
3374bool ARMAsmParser::
3375cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3376 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3377 // The second source operand must be the same register as the destination
3378 // operand.
3379 if (Operands.size() == 6 &&
Jim Grosbach459422d2011-08-19 22:30:46 +00003380 (((ARMOperand*)Operands[3])->getReg() !=
3381 ((ARMOperand*)Operands[5])->getReg()) &&
3382 (((ARMOperand*)Operands[3])->getReg() !=
3383 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach8e048492011-08-19 22:07:46 +00003384 Error(Operands[3]->getStartLoc(),
Jim Grosbach459422d2011-08-19 22:30:46 +00003385 "destination register must match source register");
Jim Grosbach8e048492011-08-19 22:07:46 +00003386 return false;
3387 }
3388 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3389 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
3390 ((ARMOperand*)Operands[4])->addRegOperands(Inst, 1);
Jim Grosbach459422d2011-08-19 22:30:46 +00003391 // If we have a three-operand form, use that, else the second source operand
3392 // is just the destination operand again.
3393 if (Operands.size() == 6)
3394 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3395 else
3396 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach8e048492011-08-19 22:07:46 +00003397 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3398
3399 return true;
3400}
Jim Grosbachcd4dd252011-08-10 22:42:16 +00003401
Jim Grosbach3ea06572011-10-24 22:16:58 +00003402bool ARMAsmParser::
3403cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3404 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3405 // Vd
3406 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3407 // Create a writeback register dummy placeholder.
3408 Inst.addOperand(MCOperand::CreateImm(0));
3409 // Vn
3410 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3411 // pred
3412 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3413 return true;
3414}
3415
3416bool ARMAsmParser::
3417cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3418 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3419 // Vd
3420 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3421 // Create a writeback register dummy placeholder.
3422 Inst.addOperand(MCOperand::CreateImm(0));
3423 // Vn
3424 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3425 // Vm
3426 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3427 // pred
3428 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3429 return true;
3430}
3431
Bill Wendlinge18980a2010-11-06 22:36:58 +00003432/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003433/// or an error. The first token must be a '[' when called.
Bill Wendling2063b842010-11-18 23:43:05 +00003434bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003435parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003436 SMLoc S, E;
Sean Callanan936b0d32010-01-19 21:44:56 +00003437 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00003438 "Token is not a Left Bracket");
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003439 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00003440 Parser.Lex(); // Eat left bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003441
Sean Callanan936b0d32010-01-19 21:44:56 +00003442 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003443 int BaseRegNum = tryParseRegister();
Jim Grosbachd3595712011-08-03 23:50:40 +00003444 if (BaseRegNum == -1)
3445 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003446
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00003447 // The next token must either be a comma or a closing bracket.
3448 const AsmToken &Tok = Parser.getTok();
3449 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbachd3595712011-08-03 23:50:40 +00003450 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00003451
Jim Grosbachd3595712011-08-03 23:50:40 +00003452 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003453 E = Tok.getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00003454 Parser.Lex(); // Eat right bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003455
Jim Grosbachd3595712011-08-03 23:50:40 +00003456 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbacha95ec992011-10-11 17:29:55 +00003457 0, 0, false, S, E));
Jim Grosbach32ff5582010-11-29 23:18:01 +00003458
Jim Grosbach40700e02011-09-19 18:42:21 +00003459 // If there's a pre-indexing writeback marker, '!', just add it as a token
3460 // operand. It's rather odd, but syntactically valid.
3461 if (Parser.getTok().is(AsmToken::Exclaim)) {
3462 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3463 Parser.Lex(); // Eat the '!'.
3464 }
3465
Jim Grosbachd3595712011-08-03 23:50:40 +00003466 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003467 }
Daniel Dunbarf5164f42011-01-18 05:34:24 +00003468
Jim Grosbachd3595712011-08-03 23:50:40 +00003469 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3470 Parser.Lex(); // Eat the comma.
Daniel Dunbarf5164f42011-01-18 05:34:24 +00003471
Jim Grosbacha95ec992011-10-11 17:29:55 +00003472 // If we have a ':', it's an alignment specifier.
3473 if (Parser.getTok().is(AsmToken::Colon)) {
3474 Parser.Lex(); // Eat the ':'.
3475 E = Parser.getTok().getLoc();
3476
3477 const MCExpr *Expr;
3478 if (getParser().ParseExpression(Expr))
3479 return true;
3480
3481 // The expression has to be a constant. Memory references with relocations
3482 // don't come through here, as they use the <label> forms of the relevant
3483 // instructions.
3484 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3485 if (!CE)
3486 return Error (E, "constant expression expected");
3487
3488 unsigned Align = 0;
3489 switch (CE->getValue()) {
3490 default:
3491 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3492 case 64: Align = 8; break;
3493 case 128: Align = 16; break;
3494 case 256: Align = 32; break;
3495 }
3496
3497 // Now we should have the closing ']'
3498 E = Parser.getTok().getLoc();
3499 if (Parser.getTok().isNot(AsmToken::RBrac))
3500 return Error(E, "']' expected");
3501 Parser.Lex(); // Eat right bracket token.
3502
3503 // Don't worry about range checking the value here. That's handled by
3504 // the is*() predicates.
3505 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3506 ARM_AM::no_shift, 0, Align,
3507 false, S, E));
3508
3509 // If there's a pre-indexing writeback marker, '!', just add it as a token
3510 // operand.
3511 if (Parser.getTok().is(AsmToken::Exclaim)) {
3512 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3513 Parser.Lex(); // Eat the '!'.
3514 }
3515
3516 return false;
3517 }
3518
3519 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbachd3595712011-08-03 23:50:40 +00003520 // offset.
3521 if (Parser.getTok().is(AsmToken::Hash)) {
3522 Parser.Lex(); // Eat the '#'.
3523 E = Parser.getTok().getLoc();
Daniel Dunbarf5164f42011-01-18 05:34:24 +00003524
Owen Anderson967674d2011-08-29 19:36:44 +00003525 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbachd3595712011-08-03 23:50:40 +00003526 const MCExpr *Offset;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003527 if (getParser().ParseExpression(Offset))
3528 return true;
Jim Grosbachd3595712011-08-03 23:50:40 +00003529
3530 // The expression has to be a constant. Memory references with relocations
3531 // don't come through here, as they use the <label> forms of the relevant
3532 // instructions.
3533 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3534 if (!CE)
3535 return Error (E, "constant expression expected");
3536
Owen Anderson967674d2011-08-29 19:36:44 +00003537 // If the constant was #-0, represent it as INT32_MIN.
3538 int32_t Val = CE->getValue();
3539 if (isNegative && Val == 0)
3540 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3541
Jim Grosbachd3595712011-08-03 23:50:40 +00003542 // Now we should have the closing ']'
3543 E = Parser.getTok().getLoc();
3544 if (Parser.getTok().isNot(AsmToken::RBrac))
3545 return Error(E, "']' expected");
3546 Parser.Lex(); // Eat right bracket token.
3547
3548 // Don't worry about range checking the value here. That's handled by
3549 // the is*() predicates.
3550 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbacha95ec992011-10-11 17:29:55 +00003551 ARM_AM::no_shift, 0, 0,
3552 false, S, E));
Jim Grosbachd3595712011-08-03 23:50:40 +00003553
3554 // If there's a pre-indexing writeback marker, '!', just add it as a token
3555 // operand.
3556 if (Parser.getTok().is(AsmToken::Exclaim)) {
3557 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3558 Parser.Lex(); // Eat the '!'.
3559 }
3560
3561 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003562 }
Jim Grosbachd3595712011-08-03 23:50:40 +00003563
3564 // The register offset is optionally preceded by a '+' or '-'
3565 bool isNegative = false;
3566 if (Parser.getTok().is(AsmToken::Minus)) {
3567 isNegative = true;
3568 Parser.Lex(); // Eat the '-'.
3569 } else if (Parser.getTok().is(AsmToken::Plus)) {
3570 // Nothing to do.
3571 Parser.Lex(); // Eat the '+'.
3572 }
3573
3574 E = Parser.getTok().getLoc();
3575 int OffsetRegNum = tryParseRegister();
3576 if (OffsetRegNum == -1)
3577 return Error(E, "register expected");
3578
3579 // If there's a shift operator, handle it.
3580 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00003581 unsigned ShiftImm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00003582 if (Parser.getTok().is(AsmToken::Comma)) {
3583 Parser.Lex(); // Eat the ','.
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00003584 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbachd3595712011-08-03 23:50:40 +00003585 return true;
3586 }
3587
3588 // Now we should have the closing ']'
3589 E = Parser.getTok().getLoc();
3590 if (Parser.getTok().isNot(AsmToken::RBrac))
3591 return Error(E, "']' expected");
3592 Parser.Lex(); // Eat right bracket token.
3593
3594 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbacha95ec992011-10-11 17:29:55 +00003595 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbachd3595712011-08-03 23:50:40 +00003596 S, E));
3597
Jim Grosbachc320c852011-08-05 21:28:30 +00003598 // If there's a pre-indexing writeback marker, '!', just add it as a token
3599 // operand.
3600 if (Parser.getTok().is(AsmToken::Exclaim)) {
3601 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3602 Parser.Lex(); // Eat the '!'.
3603 }
Jim Grosbachd3595712011-08-03 23:50:40 +00003604
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003605 return false;
3606}
3607
Jim Grosbachd3595712011-08-03 23:50:40 +00003608/// parseMemRegOffsetShift - one of these two:
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003609/// ( lsl | lsr | asr | ror ) , # shift_amount
3610/// rrx
Jim Grosbachd3595712011-08-03 23:50:40 +00003611/// return true if it parses a shift otherwise it returns false.
3612bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
3613 unsigned &Amount) {
3614 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan936b0d32010-01-19 21:44:56 +00003615 const AsmToken &Tok = Parser.getTok();
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003616 if (Tok.isNot(AsmToken::Identifier))
3617 return true;
Benjamin Kramer92d89982010-07-14 22:38:02 +00003618 StringRef ShiftName = Tok.getString();
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003619 if (ShiftName == "lsl" || ShiftName == "LSL")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003620 St = ARM_AM::lsl;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003621 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003622 St = ARM_AM::lsr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003623 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003624 St = ARM_AM::asr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003625 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003626 St = ARM_AM::ror;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003627 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003628 St = ARM_AM::rrx;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003629 else
Jim Grosbachd3595712011-08-03 23:50:40 +00003630 return Error(Loc, "illegal shift operator");
Sean Callanana83fd7d2010-01-19 20:27:46 +00003631 Parser.Lex(); // Eat shift type token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003632
Jim Grosbachd3595712011-08-03 23:50:40 +00003633 // rrx stands alone.
3634 Amount = 0;
3635 if (St != ARM_AM::rrx) {
3636 Loc = Parser.getTok().getLoc();
3637 // A '#' and a shift amount.
3638 const AsmToken &HashTok = Parser.getTok();
3639 if (HashTok.isNot(AsmToken::Hash))
3640 return Error(HashTok.getLoc(), "'#' expected");
3641 Parser.Lex(); // Eat hash token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003642
Jim Grosbachd3595712011-08-03 23:50:40 +00003643 const MCExpr *Expr;
3644 if (getParser().ParseExpression(Expr))
3645 return true;
3646 // Range check the immediate.
3647 // lsl, ror: 0 <= imm <= 31
3648 // lsr, asr: 0 <= imm <= 32
3649 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3650 if (!CE)
3651 return Error(Loc, "shift amount must be an immediate");
3652 int64_t Imm = CE->getValue();
3653 if (Imm < 0 ||
3654 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
3655 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
3656 return Error(Loc, "immediate shift value out of range");
3657 Amount = Imm;
3658 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003659
3660 return false;
3661}
3662
Jim Grosbache7fbce72011-10-03 23:38:36 +00003663/// parseFPImm - A floating point immediate expression operand.
3664ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3665parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3666 SMLoc S = Parser.getTok().getLoc();
3667
3668 if (Parser.getTok().isNot(AsmToken::Hash))
3669 return MatchOperand_NoMatch;
Jim Grosbach741cd732011-10-17 22:26:03 +00003670
3671 // Disambiguate the VMOV forms that can accept an FP immediate.
3672 // vmov.f32 <sreg>, #imm
3673 // vmov.f64 <dreg>, #imm
3674 // vmov.f32 <dreg>, #imm @ vector f32x2
3675 // vmov.f32 <qreg>, #imm @ vector f32x4
3676 //
3677 // There are also the NEON VMOV instructions which expect an
3678 // integer constant. Make sure we don't try to parse an FPImm
3679 // for these:
3680 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
3681 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
3682 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
3683 TyOp->getToken() != ".f64"))
3684 return MatchOperand_NoMatch;
3685
Jim Grosbache7fbce72011-10-03 23:38:36 +00003686 Parser.Lex(); // Eat the '#'.
3687
3688 // Handle negation, as that still comes through as a separate token.
3689 bool isNegative = false;
3690 if (Parser.getTok().is(AsmToken::Minus)) {
3691 isNegative = true;
3692 Parser.Lex();
3693 }
3694 const AsmToken &Tok = Parser.getTok();
3695 if (Tok.is(AsmToken::Real)) {
3696 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
3697 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3698 // If we had a '-' in front, toggle the sign bit.
3699 IntVal ^= (uint64_t)isNegative << 63;
3700 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
3701 Parser.Lex(); // Eat the token.
3702 if (Val == -1) {
3703 TokError("floating point value out of range");
3704 return MatchOperand_ParseFail;
3705 }
3706 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3707 return MatchOperand_Success;
3708 }
3709 if (Tok.is(AsmToken::Integer)) {
3710 int64_t Val = Tok.getIntVal();
3711 Parser.Lex(); // Eat the token.
3712 if (Val > 255 || Val < 0) {
3713 TokError("encoded floating point value out of range");
3714 return MatchOperand_ParseFail;
3715 }
3716 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3717 return MatchOperand_Success;
3718 }
3719
3720 TokError("invalid floating point immediate");
3721 return MatchOperand_ParseFail;
3722}
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003723/// Parse a arm instruction operand. For now this parses the operand regardless
3724/// of the mnemonic.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003725bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003726 StringRef Mnemonic) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003727 SMLoc S, E;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003728
3729 // Check if the current operand has a custom associated parser, if so, try to
3730 // custom parse the operand, or fallback to the general approach.
Jim Grosbach861e49c2011-02-12 01:34:40 +00003731 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3732 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003733 return false;
Jim Grosbach861e49c2011-02-12 01:34:40 +00003734 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3735 // there was a match, but an error occurred, in which case, just return that
3736 // the operand parsing failed.
3737 if (ResTy == MatchOperand_ParseFail)
3738 return true;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003739
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003740 switch (getLexer().getKind()) {
Bill Wendlingee7f1f92010-11-06 21:42:12 +00003741 default:
3742 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling2063b842010-11-18 23:43:05 +00003743 return true;
Jim Grosbachbb24c592011-07-13 18:49:30 +00003744 case AsmToken::Identifier: {
Jim Grosbach4ab23b52011-10-03 21:12:43 +00003745 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003746 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling2063b842010-11-18 23:43:05 +00003747 return false;
Jim Grosbach0d6022d2011-07-26 20:41:24 +00003748 int Res = tryParseShiftRegister(Operands);
Jim Grosbachbb24c592011-07-13 18:49:30 +00003749 if (Res == 0) // success
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003750 return false;
Jim Grosbachbb24c592011-07-13 18:49:30 +00003751 else if (Res == -1) // irrecoverable error
3752 return true;
Jim Grosbach4ab23b52011-10-03 21:12:43 +00003753 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
3754 S = Parser.getTok().getLoc();
3755 Parser.Lex();
3756 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
3757 return false;
3758 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00003759
3760 // Fall though for the Identifier case that is not a register or a
3761 // special name.
Jim Grosbachbb24c592011-07-13 18:49:30 +00003762 }
Jim Grosbach4e380352011-10-26 21:14:08 +00003763 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderbyb084be92011-01-13 20:32:36 +00003764 case AsmToken::Integer: // things like 1f and 2b as a branch targets
3765 case AsmToken::Dot: { // . as a branch target
Kevin Enderby146dcf22009-10-15 20:48:48 +00003766 // This was not a register so parse other operands that start with an
3767 // identifier (like labels) as expressions and create them as immediates.
3768 const MCExpr *IdVal;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003769 S = Parser.getTok().getLoc();
Kevin Enderby146dcf22009-10-15 20:48:48 +00003770 if (getParser().ParseExpression(IdVal))
Bill Wendling2063b842010-11-18 23:43:05 +00003771 return true;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003772 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling2063b842010-11-18 23:43:05 +00003773 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
3774 return false;
3775 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003776 case AsmToken::LBrac:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003777 return parseMemory(Operands);
Kevin Enderbya2b99102009-10-09 21:12:28 +00003778 case AsmToken::LCurly:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003779 return parseRegisterList(Operands);
Owen Andersonf02d98d2011-08-29 17:17:09 +00003780 case AsmToken::Hash: {
Kevin Enderby3a80dac2009-10-13 23:33:38 +00003781 // #42 -> immediate.
3782 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003783 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00003784 Parser.Lex();
Owen Andersonf02d98d2011-08-29 17:17:09 +00003785 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby146dcf22009-10-15 20:48:48 +00003786 const MCExpr *ImmVal;
3787 if (getParser().ParseExpression(ImmVal))
Bill Wendling2063b842010-11-18 23:43:05 +00003788 return true;
Owen Andersonf02d98d2011-08-29 17:17:09 +00003789 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
3790 if (!CE) {
3791 Error(S, "constant expression expected");
3792 return MatchOperand_ParseFail;
3793 }
3794 int32_t Val = CE->getValue();
3795 if (isNegative && Val == 0)
3796 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003797 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling2063b842010-11-18 23:43:05 +00003798 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
3799 return false;
Owen Andersonf02d98d2011-08-29 17:17:09 +00003800 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00003801 case AsmToken::Colon: {
3802 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng965b3c72011-01-13 07:58:56 +00003803 // FIXME: Check it's an expression prefix,
3804 // e.g. (FOO - :lower16:BAR) isn't legal.
3805 ARMMCExpr::VariantKind RefKind;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003806 if (parsePrefix(RefKind))
Jason W Kim1f7bc072011-01-11 23:53:41 +00003807 return true;
3808
Evan Cheng965b3c72011-01-13 07:58:56 +00003809 const MCExpr *SubExprVal;
3810 if (getParser().ParseExpression(SubExprVal))
Jason W Kim1f7bc072011-01-11 23:53:41 +00003811 return true;
3812
Evan Cheng965b3c72011-01-13 07:58:56 +00003813 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
3814 getContext());
Jason W Kim1f7bc072011-01-11 23:53:41 +00003815 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng965b3c72011-01-13 07:58:56 +00003816 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim1f7bc072011-01-11 23:53:41 +00003817 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003818 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00003819 }
3820}
3821
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003822// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng965b3c72011-01-13 07:58:56 +00003823// :lower16: and :upper16:.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003824bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng965b3c72011-01-13 07:58:56 +00003825 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim1f7bc072011-01-11 23:53:41 +00003826
3827 // :lower16: and :upper16: modifiers
Jason W Kim93229972011-01-13 00:27:00 +00003828 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim1f7bc072011-01-11 23:53:41 +00003829 Parser.Lex(); // Eat ':'
3830
3831 if (getLexer().isNot(AsmToken::Identifier)) {
3832 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
3833 return true;
3834 }
3835
3836 StringRef IDVal = Parser.getTok().getIdentifier();
3837 if (IDVal == "lower16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00003838 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00003839 } else if (IDVal == "upper16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00003840 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00003841 } else {
3842 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
3843 return true;
3844 }
3845 Parser.Lex();
3846
3847 if (getLexer().isNot(AsmToken::Colon)) {
3848 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
3849 return true;
3850 }
3851 Parser.Lex(); // Eat the last ':'
3852 return false;
3853}
3854
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003855/// \brief Given a mnemonic, split out possible predication code and carry
3856/// setting letters to form a canonical mnemonic and flags.
3857//
Daniel Dunbar876bb0182011-01-10 12:24:52 +00003858// FIXME: Would be nice to autogen this.
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003859// FIXME: This is a bit of a maze of special cases.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003860StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00003861 unsigned &PredicationCode,
3862 bool &CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003863 unsigned &ProcessorIMod,
3864 StringRef &ITMask) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003865 PredicationCode = ARMCC::AL;
3866 CarrySetting = false;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003867 ProcessorIMod = 0;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003868
Daniel Dunbar876bb0182011-01-10 12:24:52 +00003869 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003870 //
3871 // FIXME: Would be nice to autogen this.
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00003872 if ((Mnemonic == "movs" && isThumb()) ||
3873 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
3874 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
3875 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
3876 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
3877 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
3878 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
3879 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003880 return Mnemonic;
Daniel Dunbar75d26be2010-08-11 06:37:16 +00003881
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00003882 // First, split out any predication code. Ignore mnemonics we know aren't
3883 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbach8d114902011-07-20 18:20:31 +00003884 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach0c398b92011-07-27 21:58:11 +00003885 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach3636be32011-08-22 23:55:58 +00003886 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbachf6d5d602011-09-01 18:22:13 +00003887 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00003888 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
3889 .Case("eq", ARMCC::EQ)
3890 .Case("ne", ARMCC::NE)
3891 .Case("hs", ARMCC::HS)
3892 .Case("cs", ARMCC::HS)
3893 .Case("lo", ARMCC::LO)
3894 .Case("cc", ARMCC::LO)
3895 .Case("mi", ARMCC::MI)
3896 .Case("pl", ARMCC::PL)
3897 .Case("vs", ARMCC::VS)
3898 .Case("vc", ARMCC::VC)
3899 .Case("hi", ARMCC::HI)
3900 .Case("ls", ARMCC::LS)
3901 .Case("ge", ARMCC::GE)
3902 .Case("lt", ARMCC::LT)
3903 .Case("gt", ARMCC::GT)
3904 .Case("le", ARMCC::LE)
3905 .Case("al", ARMCC::AL)
3906 .Default(~0U);
3907 if (CC != ~0U) {
3908 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
3909 PredicationCode = CC;
3910 }
Bill Wendling193961b2010-10-29 23:50:21 +00003911 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00003912
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003913 // Next, determine if we have a carry setting bit. We explicitly ignore all
3914 // the instructions we know end in 's'.
3915 if (Mnemonic.endswith("s") &&
Jim Grosbachd3e8e292011-08-17 22:49:09 +00003916 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00003917 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
3918 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
3919 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach51726e22011-07-29 20:26:09 +00003920 Mnemonic == "vrsqrts" || Mnemonic == "srs" ||
3921 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003922 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
3923 CarrySetting = true;
3924 }
3925
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003926 // The "cps" instruction can have a interrupt mode operand which is glued into
3927 // the mnemonic. Check if this is the case, split it and parse the imod op
3928 if (Mnemonic.startswith("cps")) {
3929 // Split out any imod code.
3930 unsigned IMod =
3931 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
3932 .Case("ie", ARM_PROC::IE)
3933 .Case("id", ARM_PROC::ID)
3934 .Default(~0U);
3935 if (IMod != ~0U) {
3936 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
3937 ProcessorIMod = IMod;
3938 }
3939 }
3940
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003941 // The "it" instruction has the condition mask on the end of the mnemonic.
3942 if (Mnemonic.startswith("it")) {
3943 ITMask = Mnemonic.slice(2, Mnemonic.size());
3944 Mnemonic = Mnemonic.slice(0, 2);
3945 }
3946
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003947 return Mnemonic;
3948}
Daniel Dunbar5a384c82011-01-11 15:59:53 +00003949
3950/// \brief Given a canonical mnemonic, determine if the instruction ever allows
3951/// inclusion of carry set or predication code operands.
3952//
3953// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00003954void ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003955getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00003956 bool &CanAcceptPredicationCode) {
Daniel Dunbar09264122011-01-11 19:06:29 +00003957 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
3958 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00003959 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00003960 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00003961 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00003962 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00003963 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00003964 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00003965 Mnemonic == "mla" || Mnemonic == "smlal" ||
3966 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbar09264122011-01-11 19:06:29 +00003967 CanAcceptCarrySet = true;
Jim Grosbach6c45b752011-09-16 16:39:25 +00003968 } else
Daniel Dunbar09264122011-01-11 19:06:29 +00003969 CanAcceptCarrySet = false;
Daniel Dunbar5a384c82011-01-11 15:59:53 +00003970
Daniel Dunbar09264122011-01-11 19:06:29 +00003971 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
3972 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
3973 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
3974 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbach803898f2011-09-06 20:27:04 +00003975 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
3976 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach25977222011-08-19 23:24:36 +00003977 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach93981412011-10-11 21:55:36 +00003978 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
3979 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
3980 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbachb9d4e372011-08-26 22:21:51 +00003981 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
3982 !isThumb()) ||
Jim Grosbachb908b7a2011-09-10 00:15:36 +00003983 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar5a384c82011-01-11 15:59:53 +00003984 CanAcceptPredicationCode = false;
Jim Grosbach6c45b752011-09-16 16:39:25 +00003985 } else
Daniel Dunbar5a384c82011-01-11 15:59:53 +00003986 CanAcceptPredicationCode = true;
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00003987
Jim Grosbach6c45b752011-09-16 16:39:25 +00003988 if (isThumb()) {
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00003989 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbachb98ab912011-06-30 22:10:46 +00003990 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00003991 CanAcceptPredicationCode = false;
Jim Grosbach6c45b752011-09-16 16:39:25 +00003992 }
Daniel Dunbar876bb0182011-01-10 12:24:52 +00003993}
3994
Jim Grosbach7283da92011-08-16 21:12:37 +00003995bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
3996 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach1d3c1372011-09-01 00:28:52 +00003997 // FIXME: This is all horribly hacky. We really need a better way to deal
3998 // with optional operands like this in the matcher table.
Jim Grosbach7283da92011-08-16 21:12:37 +00003999
4000 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4001 // another does not. Specifically, the MOVW instruction does not. So we
4002 // special case it here and remove the defaulted (non-setting) cc_out
4003 // operand if that's the instruction we're trying to match.
4004 //
4005 // We do this as post-processing of the explicit operands rather than just
4006 // conditionally adding the cc_out in the first place because we need
4007 // to check the type of the parsed immediate operand.
Owen Andersond7791b92011-09-14 22:46:14 +00004008 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbach7283da92011-08-16 21:12:37 +00004009 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4010 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4011 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4012 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00004013
4014 // Register-register 'add' for thumb does not have a cc_out operand
4015 // when there are only two register operands.
4016 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4017 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4018 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4019 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4020 return true;
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004021 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004022 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4023 // have to check the immediate range here since Thumb2 has a variant
4024 // that can handle a different range and has a cc_out operand.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004025 if (((isThumb() && Mnemonic == "add") ||
4026 (isThumbTwo() && Mnemonic == "sub")) &&
4027 Operands.size() == 6 &&
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004028 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4029 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4030 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004031 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4032 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4033 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004034 return true;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004035 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4036 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004037 // selecting via the generic "add" mnemonic, so to know that we
4038 // should remove the cc_out operand, we have to explicitly check that
4039 // it's not one of the other variants. Ugh.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004040 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4041 Operands.size() == 6 &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004042 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4043 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4044 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4045 // Nest conditions rather than one big 'if' statement for readability.
4046 //
4047 // If either register is a high reg, it's either one of the SP
4048 // variants (handled above) or a 32-bit encoding, so we just
4049 // check against T3.
4050 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4051 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4052 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4053 return false;
4054 // If both registers are low, we're in an IT block, and the immediate is
4055 // in range, we should use encoding T1 instead, which has a cc_out.
4056 if (inITBlock() &&
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004057 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004058 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4059 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4060 return false;
4061
4062 // Otherwise, we use encoding T4, which does not have a cc_out
4063 // operand.
4064 return true;
4065 }
4066
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004067 // The thumb2 multiply instruction doesn't have a CCOut register, so
4068 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4069 // use the 16-bit encoding or not.
4070 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4071 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4072 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4073 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4074 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4075 // If the registers aren't low regs, the destination reg isn't the
4076 // same as one of the source regs, or the cc_out operand is zero
4077 // outside of an IT block, we have to use the 32-bit encoding, so
4078 // remove the cc_out operand.
4079 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4080 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4081 !inITBlock() ||
4082 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4083 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4084 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4085 static_cast<ARMOperand*>(Operands[4])->getReg())))
4086 return true;
4087
4088
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004089
Jim Grosbach4b701af2011-08-24 21:42:27 +00004090 // Register-register 'add/sub' for thumb does not have a cc_out operand
4091 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4092 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4093 // right, this will result in better diagnostics (which operand is off)
4094 // anyway.
4095 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4096 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004097 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4098 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4099 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4100 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00004101
Jim Grosbach7283da92011-08-16 21:12:37 +00004102 return false;
4103}
4104
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004105/// Parse an arm instruction mnemonic followed by its operands.
4106bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4107 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4108 // Create the leading tokens for the mnemonic, split by '.' characters.
4109 size_t Start = 0, Next = Name.find('.');
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004110 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004111
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004112 // Split out the predication code and carry setting flag from the mnemonic.
4113 unsigned PredicationCode;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004114 unsigned ProcessorIMod;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004115 bool CarrySetting;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004116 StringRef ITMask;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004117 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004118 ProcessorIMod, ITMask);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004119
Jim Grosbach1c171b12011-08-25 17:23:55 +00004120 // In Thumb1, only the branch (B) instruction can be predicated.
4121 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4122 Parser.EatToEndOfStatement();
4123 return Error(NameLoc, "conditional execution not supported in Thumb1");
4124 }
4125
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004126 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4127
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004128 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4129 // is the mask as it will be for the IT encoding if the conditional
4130 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4131 // where the conditional bit0 is zero, the instruction post-processing
4132 // will adjust the mask accordingly.
4133 if (Mnemonic == "it") {
Jim Grosbached16ec42011-08-29 22:24:09 +00004134 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4135 if (ITMask.size() > 3) {
4136 Parser.EatToEndOfStatement();
4137 return Error(Loc, "too many conditions on IT instruction");
4138 }
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004139 unsigned Mask = 8;
4140 for (unsigned i = ITMask.size(); i != 0; --i) {
4141 char pos = ITMask[i - 1];
4142 if (pos != 't' && pos != 'e') {
4143 Parser.EatToEndOfStatement();
Jim Grosbached16ec42011-08-29 22:24:09 +00004144 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004145 }
4146 Mask >>= 1;
4147 if (ITMask[i - 1] == 't')
4148 Mask |= 8;
4149 }
Jim Grosbached16ec42011-08-29 22:24:09 +00004150 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004151 }
4152
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004153 // FIXME: This is all a pretty gross hack. We should automatically handle
4154 // optional operands like this via tblgen.
Bill Wendling219dabd2010-11-21 10:56:05 +00004155
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004156 // Next, add the CCOut and ConditionCode operands, if needed.
4157 //
4158 // For mnemonics which can ever incorporate a carry setting bit or predication
4159 // code, our matching model involves us always generating CCOut and
4160 // ConditionCode operands to match the mnemonic "as written" and then we let
4161 // the matcher deal with finding the right instruction or generating an
4162 // appropriate error.
4163 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004164 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004165
Jim Grosbach03a8a162011-07-14 22:04:21 +00004166 // If we had a carry-set on an instruction that can't do that, issue an
4167 // error.
4168 if (!CanAcceptCarrySet && CarrySetting) {
4169 Parser.EatToEndOfStatement();
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004170 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach03a8a162011-07-14 22:04:21 +00004171 "' can not set flags, but 's' suffix specified");
4172 }
Jim Grosbach0a547702011-07-22 17:44:50 +00004173 // If we had a predication code on an instruction that can't do that, issue an
4174 // error.
4175 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4176 Parser.EatToEndOfStatement();
4177 return Error(NameLoc, "instruction '" + Mnemonic +
4178 "' is not predicable, but condition code specified");
4179 }
Jim Grosbach03a8a162011-07-14 22:04:21 +00004180
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004181 // Add the carry setting operand, if necessary.
Jim Grosbached16ec42011-08-29 22:24:09 +00004182 if (CanAcceptCarrySet) {
4183 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004184 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbached16ec42011-08-29 22:24:09 +00004185 Loc));
4186 }
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004187
4188 // Add the predication code operand, if necessary.
4189 if (CanAcceptPredicationCode) {
Jim Grosbached16ec42011-08-29 22:24:09 +00004190 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4191 CarrySetting);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004192 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbached16ec42011-08-29 22:24:09 +00004193 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004194 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004195
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004196 // Add the processor imod operand, if necessary.
4197 if (ProcessorIMod) {
4198 Operands.push_back(ARMOperand::CreateImm(
4199 MCConstantExpr::Create(ProcessorIMod, getContext()),
4200 NameLoc, NameLoc));
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004201 }
4202
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004203 // Add the remaining tokens in the mnemonic.
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004204 while (Next != StringRef::npos) {
4205 Start = Next;
4206 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004207 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004208
Jim Grosbach838ed3a2011-08-24 22:19:48 +00004209 // For now, we're only parsing Thumb1 (for the most part), so
4210 // just ignore ".n" qualifiers. We'll use them to restrict
4211 // matching when we do Thumb2.
Jim Grosbach39c6e1d2011-09-07 16:06:04 +00004212 if (ExtraToken != ".n") {
4213 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4214 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4215 }
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004216 }
4217
4218 // Read the remaining operands.
4219 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004220 // Read the first operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004221 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnera2a9d162010-09-11 16:18:25 +00004222 Parser.EatToEndOfStatement();
4223 return true;
4224 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004225
4226 while (getLexer().is(AsmToken::Comma)) {
Sean Callanana83fd7d2010-01-19 20:27:46 +00004227 Parser.Lex(); // Eat the comma.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004228
4229 // Parse and remember the operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004230 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnera2a9d162010-09-11 16:18:25 +00004231 Parser.EatToEndOfStatement();
4232 return true;
4233 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004234 }
4235 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00004236
Chris Lattnera2a9d162010-09-11 16:18:25 +00004237 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbachb8d9f512011-10-07 18:27:04 +00004238 SMLoc Loc = getLexer().getLoc();
Chris Lattnera2a9d162010-09-11 16:18:25 +00004239 Parser.EatToEndOfStatement();
Jim Grosbachb8d9f512011-10-07 18:27:04 +00004240 return Error(Loc, "unexpected token in argument list");
Chris Lattnera2a9d162010-09-11 16:18:25 +00004241 }
Bill Wendlingee7f1f92010-11-06 21:42:12 +00004242
Chris Lattner91689c12010-09-08 05:10:46 +00004243 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004244
Jim Grosbach7283da92011-08-16 21:12:37 +00004245 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4246 // do and don't have a cc_out optional-def operand. With some spot-checks
4247 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004248 // parse and adjust accordingly before actually matching. We shouldn't ever
4249 // try to remove a cc_out operand that was explicitly set on the the
4250 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4251 // table driven matcher doesn't fit well with the ARM instruction set.
4252 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004253 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4254 Operands.erase(Operands.begin() + 1);
4255 delete Op;
4256 }
4257
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00004258 // ARM mode 'blx' need special handling, as the register operand version
4259 // is predicable, but the label operand version is not. So, we can't rely
4260 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach6e5778f2011-10-07 23:24:09 +00004261 // a k_CondCode operand in the list. If we're trying to match the label
4262 // version, remove the k_CondCode operand here.
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00004263 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4264 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4265 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4266 Operands.erase(Operands.begin() + 1);
4267 delete Op;
4268 }
Jim Grosbach8cffa282011-08-11 23:51:13 +00004269
4270 // The vector-compare-to-zero instructions have a literal token "#0" at
4271 // the end that comes to here as an immediate operand. Convert it to a
4272 // token to play nicely with the matcher.
4273 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4274 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4275 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4276 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4277 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4278 if (CE && CE->getValue() == 0) {
4279 Operands.erase(Operands.begin() + 5);
4280 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4281 delete Op;
4282 }
4283 }
Jim Grosbach46b66462011-10-03 22:30:24 +00004284 // VCMP{E} does the same thing, but with a different operand count.
4285 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4286 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4287 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4288 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4289 if (CE && CE->getValue() == 0) {
4290 Operands.erase(Operands.begin() + 4);
4291 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4292 delete Op;
4293 }
4294 }
Jim Grosbachc3c32d92011-08-22 23:47:13 +00004295 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
4296 // end. Convert it to a token here.
4297 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
4298 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4299 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4300 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4301 if (CE && CE->getValue() == 0) {
4302 Operands.erase(Operands.begin() + 5);
4303 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4304 delete Op;
4305 }
4306 }
4307
Chris Lattnerf29c0b62010-01-14 22:21:20 +00004308 return false;
Kevin Enderbyccab3172009-09-15 00:27:25 +00004309}
4310
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004311// Validate context-sensitive operand constraints.
Jim Grosbach169b2be2011-08-23 18:13:04 +00004312
4313// return 'true' if register list contains non-low GPR registers,
4314// 'false' otherwise. If Reg is in the register list or is HiReg, set
4315// 'containsReg' to true.
4316static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4317 unsigned HiReg, bool &containsReg) {
4318 containsReg = false;
4319 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4320 unsigned OpReg = Inst.getOperand(i).getReg();
4321 if (OpReg == Reg)
4322 containsReg = true;
4323 // Anything other than a low register isn't legal here.
4324 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4325 return true;
4326 }
4327 return false;
4328}
4329
Jim Grosbacha31f2232011-09-07 18:05:34 +00004330// Check if the specified regisgter is in the register list of the inst,
4331// starting at the indicated operand number.
4332static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4333 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4334 unsigned OpReg = Inst.getOperand(i).getReg();
4335 if (OpReg == Reg)
4336 return true;
4337 }
4338 return false;
4339}
4340
Jim Grosbached16ec42011-08-29 22:24:09 +00004341// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4342// the ARMInsts array) instead. Getting that here requires awkward
4343// API changes, though. Better way?
4344namespace llvm {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00004345extern const MCInstrDesc ARMInsts[];
Jim Grosbached16ec42011-08-29 22:24:09 +00004346}
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00004347static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbached16ec42011-08-29 22:24:09 +00004348 return ARMInsts[Opcode];
4349}
4350
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004351// FIXME: We would really like to be able to tablegen'erate this.
4352bool ARMAsmParser::
4353validateInstruction(MCInst &Inst,
4354 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00004355 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbached16ec42011-08-29 22:24:09 +00004356 SMLoc Loc = Operands[0]->getStartLoc();
4357 // Check the IT block state first.
Owen Anderson44ae2da2011-09-13 17:59:19 +00004358 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4359 // being allowed in IT blocks, but not being predicable. It just always
4360 // executes.
4361 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbached16ec42011-08-29 22:24:09 +00004362 unsigned bit = 1;
4363 if (ITState.FirstCond)
4364 ITState.FirstCond = false;
4365 else
Jim Grosbacha0d34d32011-09-02 23:22:08 +00004366 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbached16ec42011-08-29 22:24:09 +00004367 // The instruction must be predicable.
4368 if (!MCID.isPredicable())
4369 return Error(Loc, "instructions in IT block must be predicable");
4370 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4371 unsigned ITCond = bit ? ITState.Cond :
4372 ARMCC::getOppositeCondition(ITState.Cond);
4373 if (Cond != ITCond) {
4374 // Find the condition code Operand to get its SMLoc information.
4375 SMLoc CondLoc;
4376 for (unsigned i = 1; i < Operands.size(); ++i)
4377 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4378 CondLoc = Operands[i]->getStartLoc();
4379 return Error(CondLoc, "incorrect condition in IT block; got '" +
4380 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4381 "', but expected '" +
4382 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4383 }
Jim Grosbachc61fc8f2011-08-31 18:29:05 +00004384 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00004385 } else if (isThumbTwo() && MCID.isPredicable() &&
4386 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson29cfe6c2011-09-09 21:48:23 +00004387 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4388 Inst.getOpcode() != ARM::t2B)
Jim Grosbached16ec42011-08-29 22:24:09 +00004389 return Error(Loc, "predicated instructions must be in IT block");
4390
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004391 switch (Inst.getOpcode()) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00004392 case ARM::LDRD:
4393 case ARM::LDRD_PRE:
4394 case ARM::LDRD_POST:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004395 case ARM::LDREXD: {
4396 // Rt2 must be Rt + 1.
4397 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4398 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4399 if (Rt2 != Rt + 1)
4400 return Error(Operands[3]->getStartLoc(),
4401 "destination operands must be sequential");
4402 return false;
4403 }
Jim Grosbacheb09f492011-08-11 20:28:23 +00004404 case ARM::STRD: {
4405 // Rt2 must be Rt + 1.
4406 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4407 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4408 if (Rt2 != Rt + 1)
4409 return Error(Operands[3]->getStartLoc(),
4410 "source operands must be sequential");
4411 return false;
4412 }
Jim Grosbachf7164b22011-08-10 20:49:18 +00004413 case ARM::STRD_PRE:
4414 case ARM::STRD_POST:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004415 case ARM::STREXD: {
4416 // Rt2 must be Rt + 1.
4417 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4418 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
4419 if (Rt2 != Rt + 1)
Jim Grosbacheb09f492011-08-11 20:28:23 +00004420 return Error(Operands[3]->getStartLoc(),
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004421 "source operands must be sequential");
4422 return false;
4423 }
Jim Grosbach03f56d92011-07-27 21:09:25 +00004424 case ARM::SBFX:
4425 case ARM::UBFX: {
4426 // width must be in range [1, 32-lsb]
4427 unsigned lsb = Inst.getOperand(2).getImm();
4428 unsigned widthm1 = Inst.getOperand(3).getImm();
4429 if (widthm1 >= 32 - lsb)
4430 return Error(Operands[5]->getStartLoc(),
4431 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach64610e52011-08-16 21:42:31 +00004432 return false;
Jim Grosbach03f56d92011-07-27 21:09:25 +00004433 }
Jim Grosbach90103cc2011-08-18 21:50:53 +00004434 case ARM::tLDMIA: {
Jim Grosbacha31f2232011-09-07 18:05:34 +00004435 // If we're parsing Thumb2, the .w variant is available and handles
4436 // most cases that are normally illegal for a Thumb1 LDM
4437 // instruction. We'll make the transformation in processInstruction()
4438 // if necessary.
4439 //
Jim Grosbach90103cc2011-08-18 21:50:53 +00004440 // Thumb LDM instructions are writeback iff the base register is not
4441 // in the register list.
4442 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach139acd22011-08-22 23:01:07 +00004443 bool hasWritebackToken =
4444 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4445 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbach169b2be2011-08-23 18:13:04 +00004446 bool listContainsBase;
Jim Grosbacha31f2232011-09-07 18:05:34 +00004447 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00004448 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4449 "registers must be in range r0-r7");
Jim Grosbach90103cc2011-08-18 21:50:53 +00004450 // If we should have writeback, then there should be a '!' token.
Jim Grosbacha31f2232011-09-07 18:05:34 +00004451 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach90103cc2011-08-18 21:50:53 +00004452 return Error(Operands[2]->getStartLoc(),
4453 "writeback operator '!' expected");
Jim Grosbacha31f2232011-09-07 18:05:34 +00004454 // If we should not have writeback, there must not be a '!'. This is
4455 // true even for the 32-bit wide encodings.
Jim Grosbach169b2be2011-08-23 18:13:04 +00004456 if (listContainsBase && hasWritebackToken)
Jim Grosbach139acd22011-08-22 23:01:07 +00004457 return Error(Operands[3]->getStartLoc(),
4458 "writeback operator '!' not allowed when base register "
4459 "in register list");
Jim Grosbach90103cc2011-08-18 21:50:53 +00004460
4461 break;
4462 }
Jim Grosbacha31f2232011-09-07 18:05:34 +00004463 case ARM::t2LDMIA_UPD: {
4464 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
4465 return Error(Operands[4]->getStartLoc(),
4466 "writeback operator '!' not allowed when base register "
4467 "in register list");
4468 break;
4469 }
Jim Grosbach38c59fc2011-08-22 23:17:34 +00004470 case ARM::tPOP: {
Jim Grosbach169b2be2011-08-23 18:13:04 +00004471 bool listContainsBase;
4472 if (checkLowRegisterList(Inst, 3, 0, ARM::PC, listContainsBase))
4473 return Error(Operands[2]->getStartLoc(),
4474 "registers must be in range r0-r7 or pc");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00004475 break;
4476 }
4477 case ARM::tPUSH: {
Jim Grosbach169b2be2011-08-23 18:13:04 +00004478 bool listContainsBase;
4479 if (checkLowRegisterList(Inst, 3, 0, ARM::LR, listContainsBase))
4480 return Error(Operands[2]->getStartLoc(),
4481 "registers must be in range r0-r7 or lr");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00004482 break;
4483 }
Jim Grosbachd80d1692011-08-23 18:15:37 +00004484 case ARM::tSTMIA_UPD: {
4485 bool listContainsBase;
Jim Grosbach099c9762011-09-16 20:50:13 +00004486 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachd80d1692011-08-23 18:15:37 +00004487 return Error(Operands[4]->getStartLoc(),
4488 "registers must be in range r0-r7");
4489 break;
4490 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004491 }
4492
4493 return false;
4494}
4495
Jim Grosbach8ba76c62011-08-11 17:35:48 +00004496void ARMAsmParser::
4497processInstruction(MCInst &Inst,
4498 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4499 switch (Inst.getOpcode()) {
4500 case ARM::LDMIA_UPD:
4501 // If this is a load of a single register via a 'pop', then we should use
4502 // a post-indexed LDR instruction instead, per the ARM ARM.
4503 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
4504 Inst.getNumOperands() == 5) {
4505 MCInst TmpInst;
4506 TmpInst.setOpcode(ARM::LDR_POST_IMM);
4507 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4508 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4509 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4510 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
4511 TmpInst.addOperand(MCOperand::CreateImm(4));
4512 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4513 TmpInst.addOperand(Inst.getOperand(3));
4514 Inst = TmpInst;
4515 }
4516 break;
Jim Grosbach27ad83d2011-08-11 18:07:11 +00004517 case ARM::STMDB_UPD:
4518 // If this is a store of a single register via a 'push', then we should use
4519 // a pre-indexed STR instruction instead, per the ARM ARM.
4520 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
4521 Inst.getNumOperands() == 5) {
4522 MCInst TmpInst;
4523 TmpInst.setOpcode(ARM::STR_PRE_IMM);
4524 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4525 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4526 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
4527 TmpInst.addOperand(MCOperand::CreateImm(-4));
4528 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4529 TmpInst.addOperand(Inst.getOperand(3));
4530 Inst = TmpInst;
4531 }
4532 break;
Jim Grosbache9ab47a2011-08-16 23:57:34 +00004533 case ARM::tADDi8:
Jim Grosbach6d606fb2011-08-31 17:07:33 +00004534 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4535 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4536 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4537 // to encoding T1 if <Rd> is omitted."
4538 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
Jim Grosbache9ab47a2011-08-16 23:57:34 +00004539 Inst.setOpcode(ARM::tADDi3);
4540 break;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004541 case ARM::tSUBi8:
4542 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4543 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4544 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4545 // to encoding T1 if <Rd> is omitted."
4546 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
4547 Inst.setOpcode(ARM::tSUBi3);
4548 break;
Owen Anderson29cfe6c2011-09-09 21:48:23 +00004549 case ARM::tB:
4550 // A Thumb conditional branch outside of an IT block is a tBcc.
4551 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4552 Inst.setOpcode(ARM::tBcc);
4553 break;
4554 case ARM::t2B:
4555 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
4556 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4557 Inst.setOpcode(ARM::t2Bcc);
4558 break;
Jim Grosbach99bc8462011-08-31 21:17:31 +00004559 case ARM::t2Bcc:
Jim Grosbacha0d34d32011-09-02 23:22:08 +00004560 // If the conditional is AL or we're in an IT block, we really want t2B.
4561 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock())
Jim Grosbach99bc8462011-08-31 21:17:31 +00004562 Inst.setOpcode(ARM::t2B);
4563 break;
Jim Grosbachcbd4ab12011-08-17 22:57:40 +00004564 case ARM::tBcc:
4565 // If the conditional is AL, we really want tB.
4566 if (Inst.getOperand(1).getImm() == ARMCC::AL)
4567 Inst.setOpcode(ARM::tB);
Jim Grosbach6ddb5682011-08-18 16:08:39 +00004568 break;
Jim Grosbacha31f2232011-09-07 18:05:34 +00004569 case ARM::tLDMIA: {
4570 // If the register list contains any high registers, or if the writeback
4571 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
4572 // instead if we're in Thumb2. Otherwise, this should have generated
4573 // an error in validateInstruction().
4574 unsigned Rn = Inst.getOperand(0).getReg();
4575 bool hasWritebackToken =
4576 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4577 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
4578 bool listContainsBase;
4579 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
4580 (!listContainsBase && !hasWritebackToken) ||
4581 (listContainsBase && hasWritebackToken)) {
4582 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4583 assert (isThumbTwo());
4584 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
4585 // If we're switching to the updating version, we need to insert
4586 // the writeback tied operand.
4587 if (hasWritebackToken)
4588 Inst.insert(Inst.begin(),
4589 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
4590 }
4591 break;
4592 }
Jim Grosbach099c9762011-09-16 20:50:13 +00004593 case ARM::tSTMIA_UPD: {
4594 // If the register list contains any high registers, we need to use
4595 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
4596 // should have generated an error in validateInstruction().
4597 unsigned Rn = Inst.getOperand(0).getReg();
4598 bool listContainsBase;
4599 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
4600 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4601 assert (isThumbTwo());
4602 Inst.setOpcode(ARM::t2STMIA_UPD);
4603 }
4604 break;
4605 }
Jim Grosbachb908b7a2011-09-10 00:15:36 +00004606 case ARM::t2MOVi: {
4607 // If we can use the 16-bit encoding and the user didn't explicitly
4608 // request the 32-bit variant, transform it here.
4609 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4610 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbach18b8b172011-09-14 19:12:11 +00004611 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
4612 Inst.getOperand(4).getReg() == ARM::CPSR) ||
4613 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbachb908b7a2011-09-10 00:15:36 +00004614 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4615 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4616 // The operands aren't in the same order for tMOVi8...
4617 MCInst TmpInst;
4618 TmpInst.setOpcode(ARM::tMOVi8);
4619 TmpInst.addOperand(Inst.getOperand(0));
4620 TmpInst.addOperand(Inst.getOperand(4));
4621 TmpInst.addOperand(Inst.getOperand(1));
4622 TmpInst.addOperand(Inst.getOperand(2));
4623 TmpInst.addOperand(Inst.getOperand(3));
4624 Inst = TmpInst;
4625 }
4626 break;
4627 }
4628 case ARM::t2MOVr: {
4629 // If we can use the 16-bit encoding and the user didn't explicitly
4630 // request the 32-bit variant, transform it here.
4631 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4632 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4633 Inst.getOperand(2).getImm() == ARMCC::AL &&
4634 Inst.getOperand(4).getReg() == ARM::CPSR &&
4635 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4636 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4637 // The operands aren't the same for tMOV[S]r... (no cc_out)
4638 MCInst TmpInst;
4639 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
4640 TmpInst.addOperand(Inst.getOperand(0));
4641 TmpInst.addOperand(Inst.getOperand(1));
4642 TmpInst.addOperand(Inst.getOperand(2));
4643 TmpInst.addOperand(Inst.getOperand(3));
4644 Inst = TmpInst;
4645 }
4646 break;
4647 }
Jim Grosbach82213192011-09-19 20:29:33 +00004648 case ARM::t2SXTH:
Jim Grosbachb3519802011-09-20 00:46:54 +00004649 case ARM::t2SXTB:
4650 case ARM::t2UXTH:
4651 case ARM::t2UXTB: {
Jim Grosbach82213192011-09-19 20:29:33 +00004652 // If we can use the 16-bit encoding and the user didn't explicitly
4653 // request the 32-bit variant, transform it here.
4654 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4655 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4656 Inst.getOperand(2).getImm() == 0 &&
4657 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4658 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbachb3519802011-09-20 00:46:54 +00004659 unsigned NewOpc;
4660 switch (Inst.getOpcode()) {
4661 default: llvm_unreachable("Illegal opcode!");
4662 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
4663 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
4664 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
4665 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
4666 }
Jim Grosbach82213192011-09-19 20:29:33 +00004667 // The operands aren't the same for thumb1 (no rotate operand).
4668 MCInst TmpInst;
4669 TmpInst.setOpcode(NewOpc);
4670 TmpInst.addOperand(Inst.getOperand(0));
4671 TmpInst.addOperand(Inst.getOperand(1));
4672 TmpInst.addOperand(Inst.getOperand(3));
4673 TmpInst.addOperand(Inst.getOperand(4));
4674 Inst = TmpInst;
4675 }
4676 break;
4677 }
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004678 case ARM::t2IT: {
4679 // The mask bits for all but the first condition are represented as
4680 // the low bit of the condition code value implies 't'. We currently
4681 // always have 1 implies 't', so XOR toggle the bits if the low bit
4682 // of the condition code is zero. The encoding also expects the low
4683 // bit of the condition to be encoded as bit 4 of the mask operand,
4684 // so mask that in if needed
4685 MCOperand &MO = Inst.getOperand(1);
4686 unsigned Mask = MO.getImm();
Jim Grosbached16ec42011-08-29 22:24:09 +00004687 unsigned OrigMask = Mask;
4688 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004689 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004690 assert(Mask && TZ <= 3 && "illegal IT mask value!");
4691 for (unsigned i = 3; i != TZ; --i)
4692 Mask ^= 1 << i;
4693 } else
4694 Mask |= 0x10;
4695 MO.setImm(Mask);
Jim Grosbached16ec42011-08-29 22:24:09 +00004696
4697 // Set up the IT block state according to the IT instruction we just
4698 // matched.
4699 assert(!inITBlock() && "nested IT blocks?!");
4700 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
4701 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
4702 ITState.CurPosition = 0;
4703 ITState.FirstCond = true;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004704 break;
4705 }
Jim Grosbach8ba76c62011-08-11 17:35:48 +00004706 }
4707}
4708
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004709unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
4710 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
4711 // suffix depending on whether they're in an IT block or not.
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00004712 unsigned Opc = Inst.getOpcode();
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00004713 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004714 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
4715 assert(MCID.hasOptionalDef() &&
4716 "optionally flag setting instruction missing optional def operand");
4717 assert(MCID.NumOperands == Inst.getNumOperands() &&
4718 "operand count mismatch!");
4719 // Find the optional-def operand (cc_out).
4720 unsigned OpNo;
4721 for (OpNo = 0;
4722 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
4723 ++OpNo)
4724 ;
4725 // If we're parsing Thumb1, reject it completely.
4726 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
4727 return Match_MnemonicFail;
4728 // If we're parsing Thumb2, which form is legal depends on whether we're
4729 // in an IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00004730 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
4731 !inITBlock())
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004732 return Match_RequiresITBlock;
Jim Grosbached16ec42011-08-29 22:24:09 +00004733 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
4734 inITBlock())
4735 return Match_RequiresNotITBlock;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004736 }
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00004737 // Some high-register supporting Thumb1 encodings only allow both registers
4738 // to be from r0-r7 when in Thumb2.
4739 else if (Opc == ARM::tADDhirr && isThumbOne() &&
4740 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4741 isARMLowRegister(Inst.getOperand(2).getReg()))
4742 return Match_RequiresThumb2;
4743 // Others only require ARMv6 or later.
Jim Grosbachf86cd372011-08-19 20:46:54 +00004744 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00004745 isARMLowRegister(Inst.getOperand(0).getReg()) &&
4746 isARMLowRegister(Inst.getOperand(1).getReg()))
4747 return Match_RequiresV6;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004748 return Match_Success;
4749}
4750
Chris Lattner9487de62010-10-28 21:28:01 +00004751bool ARMAsmParser::
4752MatchAndEmitInstruction(SMLoc IDLoc,
4753 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
4754 MCStreamer &Out) {
4755 MCInst Inst;
4756 unsigned ErrorInfo;
Jim Grosbach120a96a2011-08-15 23:03:29 +00004757 unsigned MatchResult;
Kevin Enderby3164a342010-12-09 19:19:43 +00004758 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby3164a342010-12-09 19:19:43 +00004759 switch (MatchResult) {
Jim Grosbach120a96a2011-08-15 23:03:29 +00004760 default: break;
Chris Lattnerd27b05e2010-10-28 21:41:58 +00004761 case Match_Success:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004762 // Context sensitive operand constraints aren't handled by the matcher,
4763 // so check them here.
Jim Grosbacha0d34d32011-09-02 23:22:08 +00004764 if (validateInstruction(Inst, Operands)) {
4765 // Still progress the IT block, otherwise one wrong condition causes
4766 // nasty cascading errors.
4767 forwardITPosition();
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004768 return true;
Jim Grosbacha0d34d32011-09-02 23:22:08 +00004769 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004770
Jim Grosbach8ba76c62011-08-11 17:35:48 +00004771 // Some instructions need post-processing to, for example, tweak which
4772 // encoding is selected.
4773 processInstruction(Inst, Operands);
4774
Jim Grosbacha0d34d32011-09-02 23:22:08 +00004775 // Only move forward at the very end so that everything in validate
4776 // and process gets a consistent answer about whether we're in an IT
4777 // block.
4778 forwardITPosition();
4779
Chris Lattner9487de62010-10-28 21:28:01 +00004780 Out.EmitInstruction(Inst);
4781 return false;
Chris Lattnerd27b05e2010-10-28 21:41:58 +00004782 case Match_MissingFeature:
4783 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
4784 return true;
4785 case Match_InvalidOperand: {
4786 SMLoc ErrorLoc = IDLoc;
4787 if (ErrorInfo != ~0U) {
4788 if (ErrorInfo >= Operands.size())
4789 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach624bcc72010-10-29 14:46:02 +00004790
Chris Lattnerd27b05e2010-10-28 21:41:58 +00004791 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
4792 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
4793 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00004794
Chris Lattnerd27b05e2010-10-28 21:41:58 +00004795 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattner9487de62010-10-28 21:28:01 +00004796 }
Chris Lattnerd27b05e2010-10-28 21:41:58 +00004797 case Match_MnemonicFail:
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004798 return Error(IDLoc, "invalid instruction");
Daniel Dunbar66193402011-02-04 17:12:23 +00004799 case Match_ConversionFail:
Jim Grosbach8e048492011-08-19 22:07:46 +00004800 // The converter function will have already emited a diagnostic.
4801 return true;
Jim Grosbached16ec42011-08-29 22:24:09 +00004802 case Match_RequiresNotITBlock:
4803 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004804 case Match_RequiresITBlock:
4805 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00004806 case Match_RequiresV6:
4807 return Error(IDLoc, "instruction variant requires ARMv6 or later");
4808 case Match_RequiresThumb2:
4809 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnerd27b05e2010-10-28 21:41:58 +00004810 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00004811
Eric Christopher91d7b902010-10-29 09:26:59 +00004812 llvm_unreachable("Implement any new match types added!");
Bill Wendlingee7f1f92010-11-06 21:42:12 +00004813 return true;
Chris Lattner9487de62010-10-28 21:28:01 +00004814}
4815
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004816/// parseDirective parses the arm specific directives
Kevin Enderbyccab3172009-09-15 00:27:25 +00004817bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
4818 StringRef IDVal = DirectiveID.getIdentifier();
4819 if (IDVal == ".word")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004820 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00004821 else if (IDVal == ".thumb")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004822 return parseDirectiveThumb(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00004823 else if (IDVal == ".thumb_func")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004824 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00004825 else if (IDVal == ".code")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004826 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00004827 else if (IDVal == ".syntax")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004828 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyccab3172009-09-15 00:27:25 +00004829 return true;
4830}
4831
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004832/// parseDirectiveWord
Kevin Enderbyccab3172009-09-15 00:27:25 +00004833/// ::= .word [ expression (, expression)* ]
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004834bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyccab3172009-09-15 00:27:25 +00004835 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4836 for (;;) {
4837 const MCExpr *Value;
4838 if (getParser().ParseExpression(Value))
4839 return true;
4840
Chris Lattnerc35681b2010-01-19 19:46:13 +00004841 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyccab3172009-09-15 00:27:25 +00004842
4843 if (getLexer().is(AsmToken::EndOfStatement))
4844 break;
Jim Grosbach624bcc72010-10-29 14:46:02 +00004845
Kevin Enderbyccab3172009-09-15 00:27:25 +00004846 // FIXME: Improve diagnostic.
4847 if (getLexer().isNot(AsmToken::Comma))
4848 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004849 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00004850 }
4851 }
4852
Sean Callanana83fd7d2010-01-19 20:27:46 +00004853 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00004854 return false;
4855}
4856
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004857/// parseDirectiveThumb
Kevin Enderby146dcf22009-10-15 20:48:48 +00004858/// ::= .thumb
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004859bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby146dcf22009-10-15 20:48:48 +00004860 if (getLexer().isNot(AsmToken::EndOfStatement))
4861 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004862 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004863
4864 // TODO: set thumb mode
4865 // TODO: tell the MC streamer the mode
4866 // getParser().getStreamer().Emit???();
4867 return false;
4868}
4869
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004870/// parseDirectiveThumbFunc
Kevin Enderby146dcf22009-10-15 20:48:48 +00004871/// ::= .thumbfunc symbol_name
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004872bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00004873 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
4874 bool isMachO = MAI.hasSubsectionsViaSymbols();
4875 StringRef Name;
4876
4877 // Darwin asm has function name after .thumb_func direction
4878 // ELF doesn't
4879 if (isMachO) {
4880 const AsmToken &Tok = Parser.getTok();
4881 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
4882 return Error(L, "unexpected token in .thumb_func directive");
4883 Name = Tok.getString();
4884 Parser.Lex(); // Consume the identifier token.
4885 }
4886
Kevin Enderby146dcf22009-10-15 20:48:48 +00004887 if (getLexer().isNot(AsmToken::EndOfStatement))
4888 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004889 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004890
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00004891 // FIXME: assuming function name will be the line following .thumb_func
4892 if (!isMachO) {
4893 Name = Parser.getTok().getString();
4894 }
4895
Jim Grosbachc6db8ce2010-11-05 22:33:53 +00004896 // Mark symbol as a thumb symbol.
4897 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
4898 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby146dcf22009-10-15 20:48:48 +00004899 return false;
4900}
4901
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004902/// parseDirectiveSyntax
Kevin Enderby146dcf22009-10-15 20:48:48 +00004903/// ::= .syntax unified | divided
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004904bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00004905 const AsmToken &Tok = Parser.getTok();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004906 if (Tok.isNot(AsmToken::Identifier))
4907 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer92d89982010-07-14 22:38:02 +00004908 StringRef Mode = Tok.getString();
Duncan Sands257eba42010-06-29 13:04:35 +00004909 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callanana83fd7d2010-01-19 20:27:46 +00004910 Parser.Lex();
Duncan Sands257eba42010-06-29 13:04:35 +00004911 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderbye9f2f0c2011-01-27 23:22:36 +00004912 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby146dcf22009-10-15 20:48:48 +00004913 else
4914 return Error(L, "unrecognized syntax mode in .syntax directive");
4915
4916 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan936b0d32010-01-19 21:44:56 +00004917 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004918 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004919
4920 // TODO tell the MC streamer the mode
4921 // getParser().getStreamer().Emit???();
4922 return false;
4923}
4924
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004925/// parseDirectiveCode
Kevin Enderby146dcf22009-10-15 20:48:48 +00004926/// ::= .code 16 | 32
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004927bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00004928 const AsmToken &Tok = Parser.getTok();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004929 if (Tok.isNot(AsmToken::Integer))
4930 return Error(L, "unexpected token in .code directive");
Sean Callanan936b0d32010-01-19 21:44:56 +00004931 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands257eba42010-06-29 13:04:35 +00004932 if (Val == 16)
Sean Callanana83fd7d2010-01-19 20:27:46 +00004933 Parser.Lex();
Duncan Sands257eba42010-06-29 13:04:35 +00004934 else if (Val == 32)
Sean Callanana83fd7d2010-01-19 20:27:46 +00004935 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004936 else
4937 return Error(L, "invalid operand to .code directive");
4938
4939 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan936b0d32010-01-19 21:44:56 +00004940 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004941 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004942
Evan Cheng284b4672011-07-08 22:36:29 +00004943 if (Val == 16) {
Jim Grosbachf471ac32011-09-06 18:46:23 +00004944 if (!isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00004945 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00004946 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng284b4672011-07-08 22:36:29 +00004947 } else {
Jim Grosbachf471ac32011-09-06 18:46:23 +00004948 if (isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00004949 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00004950 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Cheng45543ba2011-07-08 22:49:55 +00004951 }
Jim Grosbach2db0ea02010-11-05 22:40:53 +00004952
Kevin Enderby146dcf22009-10-15 20:48:48 +00004953 return false;
4954}
4955
Sean Callanan643a5572010-04-07 20:29:34 +00004956extern "C" void LLVMInitializeARMAsmLexer();
4957
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004958/// Force static initialization.
Kevin Enderbyccab3172009-09-15 00:27:25 +00004959extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng11424442011-07-26 00:24:13 +00004960 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
4961 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan643a5572010-04-07 20:29:34 +00004962 LLVMInitializeARMAsmLexer();
Kevin Enderbyccab3172009-09-15 00:27:25 +00004963}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00004964
Chris Lattner3e4582a2010-09-06 19:11:01 +00004965#define GET_REGISTER_MATCHER
4966#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00004967#include "ARMGenAsmMatcher.inc"