blob: 0732060c88328a8dd7e711964c137f2b9731a0e5 [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 Grosbach05df4602011-10-31 21:50:31 +0000205 bool cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
206 const SmallVectorImpl<MCParsedAsmOperand*> &);
207 bool cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
208 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000209
210 bool validateInstruction(MCInst &Inst,
211 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach8ba76c62011-08-11 17:35:48 +0000212 void processInstruction(MCInst &Inst,
213 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach7283da92011-08-16 21:12:37 +0000214 bool shouldOmitCCOutOperand(StringRef Mnemonic,
215 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000216
Kevin Enderbyccab3172009-09-15 00:27:25 +0000217public:
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000218 enum ARMMatchResultTy {
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000219 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbached16ec42011-08-29 22:24:09 +0000220 Match_RequiresNotITBlock,
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000221 Match_RequiresV6,
222 Match_RequiresThumb2
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000223 };
224
Evan Cheng91111d22011-07-09 05:47:46 +0000225 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng11424442011-07-26 00:24:13 +0000226 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Cheng4d1ca962011-07-08 01:53:10 +0000227 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng284b4672011-07-08 22:36:29 +0000228
Evan Cheng4d1ca962011-07-08 01:53:10 +0000229 // Initialize the set of available features.
Evan Cheng91111d22011-07-09 05:47:46 +0000230 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbached16ec42011-08-29 22:24:09 +0000231
232 // Not in an ITBlock to start with.
233 ITState.CurPosition = ~0U;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000234 }
Kevin Enderbyccab3172009-09-15 00:27:25 +0000235
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000236 // Implementation of the MCTargetAsmParser interface:
237 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
238 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000239 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000240 bool ParseDirective(AsmToken DirectiveID);
241
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000242 unsigned checkTargetMatchPredicate(MCInst &Inst);
243
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000244 bool MatchAndEmitInstruction(SMLoc IDLoc,
245 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
246 MCStreamer &Out);
Kevin Enderbyccab3172009-09-15 00:27:25 +0000247};
Jim Grosbach624bcc72010-10-29 14:46:02 +0000248} // end anonymous namespace
249
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +0000250namespace {
251
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000252/// ARMOperand - Instances of this class represent a parsed ARM machine
253/// instruction.
Bill Wendlingee7f1f92010-11-06 21:42:12 +0000254class ARMOperand : public MCParsedAsmOperand {
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000255 enum KindTy {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000256 k_CondCode,
257 k_CCOut,
258 k_ITCondMask,
259 k_CoprocNum,
260 k_CoprocReg,
Jim Grosbach48399582011-10-12 17:34:41 +0000261 k_CoprocOption,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000262 k_Immediate,
263 k_FPImmediate,
264 k_MemBarrierOpt,
265 k_Memory,
266 k_PostIndexRegister,
267 k_MSRMask,
268 k_ProcIFlags,
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000269 k_VectorIndex,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000270 k_Register,
271 k_RegisterList,
272 k_DPRRegisterList,
273 k_SPRRegisterList,
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000274 k_VectorList,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000275 k_ShiftedRegister,
276 k_ShiftedImmediate,
277 k_ShifterImmediate,
278 k_RotateImmediate,
279 k_BitfieldDescriptor,
280 k_Token
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000281 } Kind;
282
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000283 SMLoc StartLoc, EndLoc;
Bill Wendling0ab0f672010-11-18 21:50:54 +0000284 SmallVector<unsigned, 8> Registers;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000285
286 union {
287 struct {
Daniel Dunbard8042b72010-08-11 06:36:53 +0000288 ARMCC::CondCodes Val;
289 } CC;
290
291 struct {
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000292 unsigned Val;
293 } Cop;
294
295 struct {
Jim Grosbach48399582011-10-12 17:34:41 +0000296 unsigned Val;
297 } CoprocOption;
298
299 struct {
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000300 unsigned Mask:4;
301 } ITMask;
302
303 struct {
304 ARM_MB::MemBOpt Val;
305 } MBOpt;
306
307 struct {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000308 ARM_PROC::IFlags Val;
309 } IFlags;
310
311 struct {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000312 unsigned Val;
313 } MMask;
314
315 struct {
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000316 const char *Data;
317 unsigned Length;
318 } Tok;
319
320 struct {
321 unsigned RegNum;
322 } Reg;
323
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000324 // A vector register list is a sequential list of 1 to 4 registers.
325 struct {
326 unsigned RegNum;
327 unsigned Count;
328 } VectorList;
329
Bill Wendlingb884a8e2010-11-06 22:19:43 +0000330 struct {
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000331 unsigned Val;
332 } VectorIndex;
333
334 struct {
Kevin Enderbyf5079942009-10-13 22:19:02 +0000335 const MCExpr *Val;
336 } Imm;
Jim Grosbach624bcc72010-10-29 14:46:02 +0000337
Jim Grosbache7fbce72011-10-03 23:38:36 +0000338 struct {
339 unsigned Val; // encoded 8-bit representation
340 } FPImm;
341
Daniel Dunbar2be732a2011-01-10 15:26:21 +0000342 /// Combined record for all forms of ARM address expressions.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000343 struct {
344 unsigned BaseRegNum;
Jim Grosbachd3595712011-08-03 23:50:40 +0000345 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
346 // was specified.
347 const MCConstantExpr *OffsetImm; // Offset immediate value
348 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
349 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbacha95ec992011-10-11 17:29:55 +0000350 unsigned ShiftImm; // shift for OffsetReg.
351 unsigned Alignment; // 0 = no alignment specified
352 // n = alignment in bytes (8, 16, or 32)
Jim Grosbachd3595712011-08-03 23:50:40 +0000353 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbach871dff72011-10-11 15:59:20 +0000354 } Memory;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000355
356 struct {
Jim Grosbachd3595712011-08-03 23:50:40 +0000357 unsigned RegNum;
Jim Grosbachc320c852011-08-05 21:28:30 +0000358 bool isAdd;
359 ARM_AM::ShiftOpc ShiftTy;
360 unsigned ShiftImm;
Jim Grosbachd3595712011-08-03 23:50:40 +0000361 } PostIdxReg;
362
363 struct {
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000364 bool isASR;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000365 unsigned Imm;
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000366 } ShifterImm;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000367 struct {
368 ARM_AM::ShiftOpc ShiftTy;
369 unsigned SrcReg;
370 unsigned ShiftReg;
371 unsigned ShiftImm;
Jim Grosbachac798e12011-07-25 20:49:51 +0000372 } RegShiftedReg;
Owen Andersonb595ed02011-07-21 18:54:16 +0000373 struct {
374 ARM_AM::ShiftOpc ShiftTy;
375 unsigned SrcReg;
376 unsigned ShiftImm;
Jim Grosbachac798e12011-07-25 20:49:51 +0000377 } RegShiftedImm;
Jim Grosbach833b9d32011-07-27 20:15:40 +0000378 struct {
379 unsigned Imm;
380 } RotImm;
Jim Grosbach864b6092011-07-28 21:34:26 +0000381 struct {
382 unsigned LSB;
383 unsigned Width;
384 } Bitfield;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000385 };
Jim Grosbach624bcc72010-10-29 14:46:02 +0000386
Bill Wendlingee7f1f92010-11-06 21:42:12 +0000387 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
388public:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000389 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
390 Kind = o.Kind;
391 StartLoc = o.StartLoc;
392 EndLoc = o.EndLoc;
393 switch (Kind) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000394 case k_CondCode:
Daniel Dunbard8042b72010-08-11 06:36:53 +0000395 CC = o.CC;
396 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000397 case k_ITCondMask:
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000398 ITMask = o.ITMask;
399 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000400 case k_Token:
Daniel Dunbard8042b72010-08-11 06:36:53 +0000401 Tok = o.Tok;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000402 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000403 case k_CCOut:
404 case k_Register:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000405 Reg = o.Reg;
406 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000407 case k_RegisterList:
408 case k_DPRRegisterList:
409 case k_SPRRegisterList:
Bill Wendling0ab0f672010-11-18 21:50:54 +0000410 Registers = o.Registers;
Bill Wendling7cef4472010-11-06 19:56:04 +0000411 break;
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000412 case k_VectorList:
413 VectorList = o.VectorList;
414 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000415 case k_CoprocNum:
416 case k_CoprocReg:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000417 Cop = o.Cop;
418 break;
Jim Grosbach48399582011-10-12 17:34:41 +0000419 case k_CoprocOption:
420 CoprocOption = o.CoprocOption;
421 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000422 case k_Immediate:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000423 Imm = o.Imm;
424 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000425 case k_FPImmediate:
Jim Grosbache7fbce72011-10-03 23:38:36 +0000426 FPImm = o.FPImm;
427 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000428 case k_MemBarrierOpt:
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000429 MBOpt = o.MBOpt;
430 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000431 case k_Memory:
Jim Grosbach871dff72011-10-11 15:59:20 +0000432 Memory = o.Memory;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000433 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000434 case k_PostIndexRegister:
Jim Grosbachd3595712011-08-03 23:50:40 +0000435 PostIdxReg = o.PostIdxReg;
436 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000437 case k_MSRMask:
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000438 MMask = o.MMask;
439 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000440 case k_ProcIFlags:
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000441 IFlags = o.IFlags;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000442 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000443 case k_ShifterImmediate:
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000444 ShifterImm = o.ShifterImm;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000445 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000446 case k_ShiftedRegister:
Jim Grosbachac798e12011-07-25 20:49:51 +0000447 RegShiftedReg = o.RegShiftedReg;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000448 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000449 case k_ShiftedImmediate:
Jim Grosbachac798e12011-07-25 20:49:51 +0000450 RegShiftedImm = o.RegShiftedImm;
Owen Andersonb595ed02011-07-21 18:54:16 +0000451 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000452 case k_RotateImmediate:
Jim Grosbach833b9d32011-07-27 20:15:40 +0000453 RotImm = o.RotImm;
454 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000455 case k_BitfieldDescriptor:
Jim Grosbach864b6092011-07-28 21:34:26 +0000456 Bitfield = o.Bitfield;
457 break;
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000458 case k_VectorIndex:
459 VectorIndex = o.VectorIndex;
460 break;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000461 }
462 }
Jim Grosbach624bcc72010-10-29 14:46:02 +0000463
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000464 /// getStartLoc - Get the location of the first token of this operand.
465 SMLoc getStartLoc() const { return StartLoc; }
466 /// getEndLoc - Get the location of the last token of this operand.
467 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000468
Daniel Dunbard8042b72010-08-11 06:36:53 +0000469 ARMCC::CondCodes getCondCode() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000470 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbard8042b72010-08-11 06:36:53 +0000471 return CC.Val;
472 }
473
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000474 unsigned getCoproc() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000475 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000476 return Cop.Val;
477 }
478
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000479 StringRef getToken() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000480 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000481 return StringRef(Tok.Data, Tok.Length);
482 }
483
484 unsigned getReg() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000485 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling2cae3272010-11-09 22:44:22 +0000486 return Reg.RegNum;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000487 }
488
Bill Wendlingbed94652010-11-09 23:28:44 +0000489 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000490 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
491 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling0ab0f672010-11-18 21:50:54 +0000492 return Registers;
Bill Wendling7cef4472010-11-06 19:56:04 +0000493 }
494
Kevin Enderbyf5079942009-10-13 22:19:02 +0000495 const MCExpr *getImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000496 assert(Kind == k_Immediate && "Invalid access!");
Kevin Enderbyf5079942009-10-13 22:19:02 +0000497 return Imm.Val;
498 }
499
Jim Grosbache7fbce72011-10-03 23:38:36 +0000500 unsigned getFPImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000501 assert(Kind == k_FPImmediate && "Invalid access!");
Jim Grosbache7fbce72011-10-03 23:38:36 +0000502 return FPImm.Val;
503 }
504
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000505 unsigned getVectorIndex() const {
506 assert(Kind == k_VectorIndex && "Invalid access!");
507 return VectorIndex.Val;
508 }
509
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000510 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000511 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000512 return MBOpt.Val;
513 }
514
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000515 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000516 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000517 return IFlags.Val;
518 }
519
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000520 unsigned getMSRMask() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000521 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000522 return MMask.Val;
523 }
524
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000525 bool isCoprocNum() const { return Kind == k_CoprocNum; }
526 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach48399582011-10-12 17:34:41 +0000527 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000528 bool isCondCode() const { return Kind == k_CondCode; }
529 bool isCCOut() const { return Kind == k_CCOut; }
530 bool isITMask() const { return Kind == k_ITCondMask; }
531 bool isITCondCode() const { return Kind == k_CondCode; }
532 bool isImm() const { return Kind == k_Immediate; }
533 bool isFPImm() const { return Kind == k_FPImmediate; }
Jim Grosbach7db8d692011-09-08 22:07:06 +0000534 bool isImm8s4() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000535 if (Kind != k_Immediate)
Jim Grosbach7db8d692011-09-08 22:07:06 +0000536 return false;
537 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
538 if (!CE) return false;
539 int64_t Value = CE->getValue();
540 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
541 }
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000542 bool isImm0_1020s4() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000543 if (Kind != k_Immediate)
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000544 return false;
545 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
546 if (!CE) return false;
547 int64_t Value = CE->getValue();
548 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
549 }
550 bool isImm0_508s4() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000551 if (Kind != k_Immediate)
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000552 return false;
553 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
554 if (!CE) return false;
555 int64_t Value = CE->getValue();
556 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
557 }
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000558 bool isImm0_255() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000559 if (Kind != k_Immediate)
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000560 return false;
561 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
562 if (!CE) return false;
563 int64_t Value = CE->getValue();
564 return Value >= 0 && Value < 256;
565 }
Jim Grosbach31756c22011-07-13 22:01:08 +0000566 bool isImm0_7() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000567 if (Kind != k_Immediate)
Jim Grosbach31756c22011-07-13 22:01:08 +0000568 return false;
569 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
570 if (!CE) return false;
571 int64_t Value = CE->getValue();
572 return Value >= 0 && Value < 8;
573 }
574 bool isImm0_15() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000575 if (Kind != k_Immediate)
Jim Grosbach31756c22011-07-13 22:01:08 +0000576 return false;
577 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
578 if (!CE) return false;
579 int64_t Value = CE->getValue();
580 return Value >= 0 && Value < 16;
581 }
Jim Grosbach72e7c4f2011-07-21 23:26:25 +0000582 bool isImm0_31() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000583 if (Kind != k_Immediate)
Jim Grosbach72e7c4f2011-07-21 23:26:25 +0000584 return false;
585 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
586 if (!CE) return false;
587 int64_t Value = CE->getValue();
588 return Value >= 0 && Value < 32;
589 }
Jim Grosbach475c6db2011-07-25 23:09:14 +0000590 bool isImm1_16() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000591 if (Kind != k_Immediate)
Jim Grosbach475c6db2011-07-25 23:09:14 +0000592 return false;
593 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
594 if (!CE) return false;
595 int64_t Value = CE->getValue();
596 return Value > 0 && Value < 17;
597 }
Jim Grosbach801e0a32011-07-22 23:16:18 +0000598 bool isImm1_32() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000599 if (Kind != k_Immediate)
Jim Grosbach801e0a32011-07-22 23:16:18 +0000600 return false;
601 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
602 if (!CE) return false;
603 int64_t Value = CE->getValue();
604 return Value > 0 && Value < 33;
605 }
Jim Grosbach975b6412011-07-13 20:10:10 +0000606 bool isImm0_65535() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000607 if (Kind != k_Immediate)
Jim Grosbach975b6412011-07-13 20:10:10 +0000608 return false;
609 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
610 if (!CE) return false;
611 int64_t Value = CE->getValue();
612 return Value >= 0 && Value < 65536;
613 }
Jim Grosbach7c09e3c2011-07-19 19:13:28 +0000614 bool isImm0_65535Expr() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000615 if (Kind != k_Immediate)
Jim Grosbach7c09e3c2011-07-19 19:13:28 +0000616 return false;
617 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
618 // If it's not a constant expression, it'll generate a fixup and be
619 // handled later.
620 if (!CE) return true;
621 int64_t Value = CE->getValue();
622 return Value >= 0 && Value < 65536;
623 }
Jim Grosbachf1637842011-07-26 16:24:27 +0000624 bool isImm24bit() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000625 if (Kind != k_Immediate)
Jim Grosbachf1637842011-07-26 16:24:27 +0000626 return false;
627 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
628 if (!CE) return false;
629 int64_t Value = CE->getValue();
630 return Value >= 0 && Value <= 0xffffff;
631 }
Jim Grosbach46dd4132011-08-17 21:51:27 +0000632 bool isImmThumbSR() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000633 if (Kind != k_Immediate)
Jim Grosbach46dd4132011-08-17 21:51:27 +0000634 return false;
635 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
636 if (!CE) return false;
637 int64_t Value = CE->getValue();
638 return Value > 0 && Value < 33;
639 }
Jim Grosbach27c1e252011-07-21 17:23:04 +0000640 bool isPKHLSLImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000641 if (Kind != k_Immediate)
Jim Grosbach27c1e252011-07-21 17:23:04 +0000642 return false;
643 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
644 if (!CE) return false;
645 int64_t Value = CE->getValue();
646 return Value >= 0 && Value < 32;
647 }
648 bool isPKHASRImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000649 if (Kind != k_Immediate)
Jim Grosbach27c1e252011-07-21 17:23:04 +0000650 return false;
651 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
652 if (!CE) return false;
653 int64_t Value = CE->getValue();
654 return Value > 0 && Value <= 32;
655 }
Jim Grosbach9720dcf2011-07-19 16:50:30 +0000656 bool isARMSOImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000657 if (Kind != k_Immediate)
Jim Grosbach9720dcf2011-07-19 16:50:30 +0000658 return false;
659 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
660 if (!CE) return false;
661 int64_t Value = CE->getValue();
662 return ARM_AM::getSOImmVal(Value) != -1;
663 }
Jim Grosbach3d785ed2011-10-28 22:50:54 +0000664 bool isARMSOImmNot() const {
665 if (Kind != k_Immediate)
666 return false;
667 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
668 if (!CE) return false;
669 int64_t Value = CE->getValue();
670 return ARM_AM::getSOImmVal(~Value) != -1;
671 }
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000672 bool isT2SOImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000673 if (Kind != k_Immediate)
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000674 return false;
675 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
676 if (!CE) return false;
677 int64_t Value = CE->getValue();
678 return ARM_AM::getT2SOImmVal(Value) != -1;
679 }
Jim Grosbachb009a872011-10-28 22:36:30 +0000680 bool isT2SOImmNot() const {
681 if (Kind != k_Immediate)
682 return false;
683 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
684 if (!CE) return false;
685 int64_t Value = CE->getValue();
686 return ARM_AM::getT2SOImmVal(~Value) != -1;
687 }
Jim Grosbach0a547702011-07-22 17:44:50 +0000688 bool isSetEndImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000689 if (Kind != k_Immediate)
Jim Grosbach0a547702011-07-22 17:44:50 +0000690 return false;
691 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
692 if (!CE) return false;
693 int64_t Value = CE->getValue();
694 return Value == 1 || Value == 0;
695 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000696 bool isReg() const { return Kind == k_Register; }
697 bool isRegList() const { return Kind == k_RegisterList; }
698 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
699 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
700 bool isToken() const { return Kind == k_Token; }
701 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
702 bool isMemory() const { return Kind == k_Memory; }
703 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
704 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
705 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
706 bool isRotImm() const { return Kind == k_RotateImmediate; }
707 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
708 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachc320c852011-08-05 21:28:30 +0000709 bool isPostIdxReg() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000710 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy == ARM_AM::no_shift;
Jim Grosbachc320c852011-08-05 21:28:30 +0000711 }
Jim Grosbacha95ec992011-10-11 17:29:55 +0000712 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachc11b7c32011-10-10 23:06:42 +0000713 if (!isMemory())
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000714 return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000715 // No offset of any kind.
Jim Grosbacha95ec992011-10-11 17:29:55 +0000716 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
717 (alignOK || Memory.Alignment == 0);
718 }
719 bool isAlignedMemory() const {
720 return isMemNoOffset(true);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000721 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000722 bool isAddrMode2() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000723 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000724 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000725 if (Memory.OffsetRegNum) return true;
Jim Grosbachd3595712011-08-03 23:50:40 +0000726 // Immediate offset in range [-4095, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +0000727 if (!Memory.OffsetImm) return true;
728 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachd3595712011-08-03 23:50:40 +0000729 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +0000730 }
Jim Grosbachcd17c122011-08-04 23:01:30 +0000731 bool isAM2OffsetImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000732 if (Kind != k_Immediate)
Jim Grosbachcd17c122011-08-04 23:01:30 +0000733 return false;
734 // Immediate offset in range [-4095, 4095].
735 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
736 if (!CE) return false;
737 int64_t Val = CE->getValue();
738 return Val > -4096 && Val < 4096;
739 }
Jim Grosbach5b96b802011-08-10 20:29:19 +0000740 bool isAddrMode3() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000741 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000742 // No shifts are legal for AM3.
Jim Grosbach871dff72011-10-11 15:59:20 +0000743 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000744 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000745 if (Memory.OffsetRegNum) return true;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000746 // Immediate offset in range [-255, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +0000747 if (!Memory.OffsetImm) return true;
748 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach5b96b802011-08-10 20:29:19 +0000749 return Val > -256 && Val < 256;
750 }
751 bool isAM3Offset() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000752 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach5b96b802011-08-10 20:29:19 +0000753 return false;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000754 if (Kind == k_PostIndexRegister)
Jim Grosbach5b96b802011-08-10 20:29:19 +0000755 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
756 // Immediate offset in range [-255, 255].
757 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
758 if (!CE) return false;
759 int64_t Val = CE->getValue();
Jim Grosbach1d9d5e92011-08-10 21:56:18 +0000760 // Special case, #-0 is INT32_MIN.
761 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000762 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000763 bool isAddrMode5() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000764 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000765 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000766 if (Memory.OffsetRegNum) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000767 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbach871dff72011-10-11 15:59:20 +0000768 if (!Memory.OffsetImm) return true;
769 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson967674d2011-08-29 19:36:44 +0000770 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
771 Val == INT32_MIN;
Bill Wendling8d2aa032010-11-08 23:49:57 +0000772 }
Jim Grosbach05541f42011-09-19 22:21:13 +0000773 bool isMemTBB() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000774 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000775 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach05541f42011-09-19 22:21:13 +0000776 return false;
777 return true;
778 }
779 bool isMemTBH() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000780 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000781 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
782 Memory.Alignment != 0 )
Jim Grosbach05541f42011-09-19 22:21:13 +0000783 return false;
784 return true;
785 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000786 bool isMemRegOffset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000787 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendling092a7bd2010-12-14 03:36:38 +0000788 return false;
Daniel Dunbar7ed45592011-01-18 05:34:11 +0000789 return true;
Bill Wendling092a7bd2010-12-14 03:36:38 +0000790 }
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000791 bool isT2MemRegOffset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000792 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
793 Memory.Alignment != 0)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000794 return false;
795 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbach871dff72011-10-11 15:59:20 +0000796 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000797 return true;
Jim Grosbach871dff72011-10-11 15:59:20 +0000798 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000799 return false;
800 return true;
801 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000802 bool isMemThumbRR() const {
803 // Thumb reg+reg addressing is simple. Just two registers, a base and
804 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbach871dff72011-10-11 15:59:20 +0000805 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000806 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendling811c9362010-11-30 07:44:32 +0000807 return false;
Jim Grosbach871dff72011-10-11 15:59:20 +0000808 return isARMLowRegister(Memory.BaseRegNum) &&
809 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach3fe94e32011-08-19 17:55:24 +0000810 }
811 bool isMemThumbRIs4() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000812 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000813 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach3fe94e32011-08-19 17:55:24 +0000814 return false;
815 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbach871dff72011-10-11 15:59:20 +0000816 if (!Memory.OffsetImm) return true;
817 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach23983d62011-08-19 18:13:48 +0000818 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
819 }
Jim Grosbach26d35872011-08-19 18:55:51 +0000820 bool isMemThumbRIs2() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000821 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000822 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach26d35872011-08-19 18:55:51 +0000823 return false;
824 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbach871dff72011-10-11 15:59:20 +0000825 if (!Memory.OffsetImm) return true;
826 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach26d35872011-08-19 18:55:51 +0000827 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
828 }
Jim Grosbacha32c7532011-08-19 18:49:59 +0000829 bool isMemThumbRIs1() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000830 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000831 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbacha32c7532011-08-19 18:49:59 +0000832 return false;
833 // Immediate offset in range [0, 31].
Jim Grosbach871dff72011-10-11 15:59:20 +0000834 if (!Memory.OffsetImm) return true;
835 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha32c7532011-08-19 18:49:59 +0000836 return Val >= 0 && Val <= 31;
837 }
Jim Grosbach23983d62011-08-19 18:13:48 +0000838 bool isMemThumbSPI() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000839 if (!isMemory() || Memory.OffsetRegNum != 0 ||
840 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbach23983d62011-08-19 18:13:48 +0000841 return false;
842 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +0000843 if (!Memory.OffsetImm) return true;
844 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach23983d62011-08-19 18:13:48 +0000845 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendling811c9362010-11-30 07:44:32 +0000846 }
Jim Grosbach7db8d692011-09-08 22:07:06 +0000847 bool isMemImm8s4Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000848 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7db8d692011-09-08 22:07:06 +0000849 return false;
850 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +0000851 if (!Memory.OffsetImm) return true;
852 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7db8d692011-09-08 22:07:06 +0000853 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
854 }
Jim Grosbacha05627e2011-09-09 18:37:27 +0000855 bool isMemImm0_1020s4Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000856 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha05627e2011-09-09 18:37:27 +0000857 return false;
858 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +0000859 if (!Memory.OffsetImm) return true;
860 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha05627e2011-09-09 18:37:27 +0000861 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
862 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000863 bool isMemImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000864 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachd3595712011-08-03 23:50:40 +0000865 return false;
866 // Immediate offset in range [-255, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +0000867 if (!Memory.OffsetImm) return true;
868 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson49168402011-09-23 22:25:02 +0000869 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbachd3595712011-08-03 23:50:40 +0000870 }
Jim Grosbach2392c532011-09-07 23:39:14 +0000871 bool isMemPosImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000872 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach2392c532011-09-07 23:39:14 +0000873 return false;
874 // Immediate offset in range [0, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +0000875 if (!Memory.OffsetImm) return true;
876 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2392c532011-09-07 23:39:14 +0000877 return Val >= 0 && Val < 256;
878 }
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +0000879 bool isMemNegImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000880 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +0000881 return false;
882 // Immediate offset in range [-255, -1].
Jim Grosbach871dff72011-10-11 15:59:20 +0000883 if (!Memory.OffsetImm) return true;
884 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +0000885 return Val > -256 && Val < 0;
886 }
887 bool isMemUImm12Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000888 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +0000889 return false;
890 // Immediate offset in range [0, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +0000891 if (!Memory.OffsetImm) return true;
892 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +0000893 return (Val >= 0 && Val < 4096);
894 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000895 bool isMemImm12Offset() const {
Jim Grosbach95466ce2011-08-08 20:59:31 +0000896 // If we have an immediate that's not a constant, treat it as a label
897 // reference needing a fixup. If it is a constant, it's something else
898 // and we reject it.
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000899 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach95466ce2011-08-08 20:59:31 +0000900 return true;
901
Jim Grosbacha95ec992011-10-11 17:29:55 +0000902 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachd3595712011-08-03 23:50:40 +0000903 return false;
904 // Immediate offset in range [-4095, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +0000905 if (!Memory.OffsetImm) return true;
906 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson967674d2011-08-29 19:36:44 +0000907 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbachd3595712011-08-03 23:50:40 +0000908 }
909 bool isPostIdxImm8() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000910 if (Kind != k_Immediate)
Jim Grosbachd3595712011-08-03 23:50:40 +0000911 return false;
912 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
913 if (!CE) return false;
914 int64_t Val = CE->getValue();
Owen Andersonf02d98d2011-08-29 17:17:09 +0000915 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbachd3595712011-08-03 23:50:40 +0000916 }
Jim Grosbach93981412011-10-11 21:55:36 +0000917 bool isPostIdxImm8s4() const {
918 if (Kind != k_Immediate)
919 return false;
920 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
921 if (!CE) return false;
922 int64_t Val = CE->getValue();
923 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
924 (Val == INT32_MIN);
925 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000926
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000927 bool isMSRMask() const { return Kind == k_MSRMask; }
928 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +0000929
Jim Grosbach741cd732011-10-17 22:26:03 +0000930 // NEON operands.
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000931 bool isVecListOneD() const {
932 if (Kind != k_VectorList) return false;
933 return VectorList.Count == 1;
934 }
935
Jim Grosbach2f2e3c42011-10-21 18:54:25 +0000936 bool isVecListTwoD() const {
937 if (Kind != k_VectorList) return false;
938 return VectorList.Count == 2;
939 }
940
Jim Grosbachc4360fe2011-10-21 20:02:19 +0000941 bool isVecListThreeD() const {
942 if (Kind != k_VectorList) return false;
943 return VectorList.Count == 3;
944 }
945
Jim Grosbach846bcff2011-10-21 20:35:01 +0000946 bool isVecListFourD() const {
947 if (Kind != k_VectorList) return false;
948 return VectorList.Count == 4;
949 }
950
Jim Grosbach118b38c2011-10-21 22:21:10 +0000951 bool isVecListTwoQ() const {
952 if (Kind != k_VectorList) return false;
953 //FIXME: We haven't taught the parser to handle by-two register lists
954 // yet, so don't pretend to know one.
955 return VectorList.Count == 2 && false;
956 }
957
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000958 bool isVectorIndex8() const {
959 if (Kind != k_VectorIndex) return false;
960 return VectorIndex.Val < 8;
961 }
962 bool isVectorIndex16() const {
963 if (Kind != k_VectorIndex) return false;
964 return VectorIndex.Val < 4;
965 }
966 bool isVectorIndex32() const {
967 if (Kind != k_VectorIndex) return false;
968 return VectorIndex.Val < 2;
969 }
970
Jim Grosbach741cd732011-10-17 22:26:03 +0000971 bool isNEONi8splat() const {
972 if (Kind != k_Immediate)
973 return false;
974 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
975 // Must be a constant.
976 if (!CE) return false;
977 int64_t Value = CE->getValue();
978 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
979 // value.
Jim Grosbach741cd732011-10-17 22:26:03 +0000980 return Value >= 0 && Value < 256;
981 }
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000982
Jim Grosbachcda32ae2011-10-17 23:09:09 +0000983 bool isNEONi16splat() const {
984 if (Kind != k_Immediate)
985 return false;
986 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
987 // Must be a constant.
988 if (!CE) return false;
989 int64_t Value = CE->getValue();
990 // i16 value in the range [0,255] or [0x0100, 0xff00]
991 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
992 }
993
Jim Grosbach8211c052011-10-18 00:22:00 +0000994 bool isNEONi32splat() const {
995 if (Kind != k_Immediate)
996 return false;
997 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
998 // Must be a constant.
999 if (!CE) return false;
1000 int64_t Value = CE->getValue();
1001 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1002 return (Value >= 0 && Value < 256) ||
1003 (Value >= 0x0100 && Value <= 0xff00) ||
1004 (Value >= 0x010000 && Value <= 0xff0000) ||
1005 (Value >= 0x01000000 && Value <= 0xff000000);
1006 }
1007
1008 bool isNEONi32vmov() const {
1009 if (Kind != k_Immediate)
1010 return false;
1011 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1012 // Must be a constant.
1013 if (!CE) return false;
1014 int64_t Value = CE->getValue();
1015 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1016 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1017 return (Value >= 0 && Value < 256) ||
1018 (Value >= 0x0100 && Value <= 0xff00) ||
1019 (Value >= 0x010000 && Value <= 0xff0000) ||
1020 (Value >= 0x01000000 && Value <= 0xff000000) ||
1021 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1022 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1023 }
1024
Jim Grosbache4454e02011-10-18 16:18:11 +00001025 bool isNEONi64splat() const {
1026 if (Kind != k_Immediate)
1027 return false;
1028 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1029 // Must be a constant.
1030 if (!CE) return false;
1031 uint64_t Value = CE->getValue();
1032 // i64 value with each byte being either 0 or 0xff.
1033 for (unsigned i = 0; i < 8; ++i)
1034 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1035 return true;
1036 }
1037
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001038 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner5d6f6a02010-10-29 00:27:31 +00001039 // Add as immediates when possible. Null MCExpr = 0.
1040 if (Expr == 0)
1041 Inst.addOperand(MCOperand::CreateImm(0));
1042 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001043 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1044 else
1045 Inst.addOperand(MCOperand::CreateExpr(Expr));
1046 }
1047
Daniel Dunbard8042b72010-08-11 06:36:53 +00001048 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001049 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbard8042b72010-08-11 06:36:53 +00001050 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach968c9272010-12-06 18:30:57 +00001051 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1052 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbard8042b72010-08-11 06:36:53 +00001053 }
1054
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001055 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1056 assert(N == 1 && "Invalid number of operands!");
1057 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1058 }
1059
Jim Grosbach48399582011-10-12 17:34:41 +00001060 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1061 assert(N == 1 && "Invalid number of operands!");
1062 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1063 }
1064
1065 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1066 assert(N == 1 && "Invalid number of operands!");
1067 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1068 }
1069
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001070 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1071 assert(N == 1 && "Invalid number of operands!");
1072 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1073 }
1074
1075 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1076 assert(N == 1 && "Invalid number of operands!");
1077 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1078 }
1079
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001080 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1081 assert(N == 1 && "Invalid number of operands!");
1082 Inst.addOperand(MCOperand::CreateReg(getReg()));
1083 }
1084
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001085 void addRegOperands(MCInst &Inst, unsigned N) const {
1086 assert(N == 1 && "Invalid number of operands!");
1087 Inst.addOperand(MCOperand::CreateReg(getReg()));
1088 }
1089
Jim Grosbachac798e12011-07-25 20:49:51 +00001090 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001091 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachac798e12011-07-25 20:49:51 +00001092 assert(isRegShiftedReg() && "addRegShiftedRegOperands() on non RegShiftedReg!");
1093 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1094 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001095 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachac798e12011-07-25 20:49:51 +00001096 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001097 }
1098
Jim Grosbachac798e12011-07-25 20:49:51 +00001099 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson04912702011-07-21 23:38:37 +00001100 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachac798e12011-07-25 20:49:51 +00001101 assert(isRegShiftedImm() && "addRegShiftedImmOperands() on non RegShiftedImm!");
1102 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Andersonb595ed02011-07-21 18:54:16 +00001103 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachac798e12011-07-25 20:49:51 +00001104 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Andersonb595ed02011-07-21 18:54:16 +00001105 }
1106
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001107 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001108 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001109 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1110 ShifterImm.Imm));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001111 }
1112
Bill Wendling8d2aa032010-11-08 23:49:57 +00001113 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling2cae3272010-11-09 22:44:22 +00001114 assert(N == 1 && "Invalid number of operands!");
Bill Wendlingbed94652010-11-09 23:28:44 +00001115 const SmallVectorImpl<unsigned> &RegList = getRegList();
1116 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00001117 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1118 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling8d2aa032010-11-08 23:49:57 +00001119 }
1120
Bill Wendling9898ac92010-11-17 04:32:08 +00001121 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1122 addRegListOperands(Inst, N);
1123 }
1124
1125 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1126 addRegListOperands(Inst, N);
1127 }
1128
Jim Grosbach833b9d32011-07-27 20:15:40 +00001129 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1130 assert(N == 1 && "Invalid number of operands!");
1131 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1132 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1133 }
1134
Jim Grosbach864b6092011-07-28 21:34:26 +00001135 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1136 assert(N == 1 && "Invalid number of operands!");
1137 // Munge the lsb/width into a bitfield mask.
1138 unsigned lsb = Bitfield.LSB;
1139 unsigned width = Bitfield.Width;
1140 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1141 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1142 (32 - (lsb + width)));
1143 Inst.addOperand(MCOperand::CreateImm(Mask));
1144 }
1145
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001146 void addImmOperands(MCInst &Inst, unsigned N) const {
1147 assert(N == 1 && "Invalid number of operands!");
1148 addExpr(Inst, getImm());
1149 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00001150
Jim Grosbache7fbce72011-10-03 23:38:36 +00001151 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1152 assert(N == 1 && "Invalid number of operands!");
1153 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1154 }
1155
Jim Grosbach7db8d692011-09-08 22:07:06 +00001156 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1157 assert(N == 1 && "Invalid number of operands!");
1158 // FIXME: We really want to scale the value here, but the LDRD/STRD
1159 // instruction don't encode operands that way yet.
1160 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1161 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1162 }
1163
Jim Grosbach0a0b3072011-08-24 21:22:15 +00001164 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1165 assert(N == 1 && "Invalid number of operands!");
1166 // The immediate is scaled by four in the encoding and is stored
1167 // in the MCInst as such. Lop off the low two bits here.
1168 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1169 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1170 }
1171
1172 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1173 assert(N == 1 && "Invalid number of operands!");
1174 // The immediate is scaled by four in the encoding and is stored
1175 // in the MCInst as such. Lop off the low two bits here.
1176 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1177 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1178 }
1179
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +00001180 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1181 assert(N == 1 && "Invalid number of operands!");
1182 addExpr(Inst, getImm());
1183 }
1184
Jim Grosbach31756c22011-07-13 22:01:08 +00001185 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1186 assert(N == 1 && "Invalid number of operands!");
1187 addExpr(Inst, getImm());
1188 }
1189
1190 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1191 assert(N == 1 && "Invalid number of operands!");
1192 addExpr(Inst, getImm());
1193 }
1194
Jim Grosbach72e7c4f2011-07-21 23:26:25 +00001195 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1196 assert(N == 1 && "Invalid number of operands!");
1197 addExpr(Inst, getImm());
1198 }
1199
Jim Grosbach475c6db2011-07-25 23:09:14 +00001200 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1201 assert(N == 1 && "Invalid number of operands!");
1202 // The constant encodes as the immediate-1, and we store in the instruction
1203 // the bits as encoded, so subtract off one here.
1204 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1205 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1206 }
1207
Jim Grosbach801e0a32011-07-22 23:16:18 +00001208 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1209 assert(N == 1 && "Invalid number of operands!");
1210 // The constant encodes as the immediate-1, and we store in the instruction
1211 // the bits as encoded, so subtract off one here.
1212 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1213 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1214 }
1215
Jim Grosbach975b6412011-07-13 20:10:10 +00001216 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1217 assert(N == 1 && "Invalid number of operands!");
1218 addExpr(Inst, getImm());
1219 }
1220
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00001221 void addImm0_65535ExprOperands(MCInst &Inst, unsigned N) const {
1222 assert(N == 1 && "Invalid number of operands!");
1223 addExpr(Inst, getImm());
1224 }
1225
Jim Grosbachf1637842011-07-26 16:24:27 +00001226 void addImm24bitOperands(MCInst &Inst, unsigned N) const {
1227 assert(N == 1 && "Invalid number of operands!");
1228 addExpr(Inst, getImm());
1229 }
1230
Jim Grosbach46dd4132011-08-17 21:51:27 +00001231 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1232 assert(N == 1 && "Invalid number of operands!");
1233 // The constant encodes as the immediate, except for 32, which encodes as
1234 // zero.
1235 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1236 unsigned Imm = CE->getValue();
1237 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1238 }
1239
Jim Grosbach27c1e252011-07-21 17:23:04 +00001240 void addPKHLSLImmOperands(MCInst &Inst, unsigned N) const {
1241 assert(N == 1 && "Invalid number of operands!");
1242 addExpr(Inst, getImm());
1243 }
1244
1245 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1246 assert(N == 1 && "Invalid number of operands!");
1247 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1248 // the instruction as well.
1249 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1250 int Val = CE->getValue();
1251 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1252 }
1253
Jim Grosbach9720dcf2011-07-19 16:50:30 +00001254 void addARMSOImmOperands(MCInst &Inst, unsigned N) const {
1255 assert(N == 1 && "Invalid number of operands!");
1256 addExpr(Inst, getImm());
1257 }
1258
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +00001259 void addT2SOImmOperands(MCInst &Inst, unsigned N) const {
1260 assert(N == 1 && "Invalid number of operands!");
1261 addExpr(Inst, getImm());
1262 }
1263
Jim Grosbachb009a872011-10-28 22:36:30 +00001264 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1265 assert(N == 1 && "Invalid number of operands!");
1266 // The operand is actually a t2_so_imm, but we have its bitwise
1267 // negation in the assembly source, so twiddle it here.
1268 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1269 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1270 }
1271
Jim Grosbach3d785ed2011-10-28 22:50:54 +00001272 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1273 assert(N == 1 && "Invalid number of operands!");
1274 // The operand is actually a so_imm, but we have its bitwise
1275 // negation in the assembly source, so twiddle it here.
1276 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1277 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1278 }
1279
Jim Grosbach0a547702011-07-22 17:44:50 +00001280 void addSetEndImmOperands(MCInst &Inst, unsigned N) const {
1281 assert(N == 1 && "Invalid number of operands!");
1282 addExpr(Inst, getImm());
1283 }
1284
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001285 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1286 assert(N == 1 && "Invalid number of operands!");
1287 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1288 }
1289
Jim Grosbachd3595712011-08-03 23:50:40 +00001290 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1291 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001292 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopesf170f8b2011-03-24 21:04:58 +00001293 }
1294
Jim Grosbacha95ec992011-10-11 17:29:55 +00001295 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1296 assert(N == 2 && "Invalid number of operands!");
1297 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1298 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1299 }
1300
Jim Grosbachd3595712011-08-03 23:50:40 +00001301 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1302 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001303 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1304 if (!Memory.OffsetRegNum) {
Jim Grosbachd3595712011-08-03 23:50:40 +00001305 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1306 // Special case for #-0
1307 if (Val == INT32_MIN) Val = 0;
1308 if (Val < 0) Val = -Val;
1309 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1310 } else {
1311 // For register offset, we encode the shift type and negation flag
1312 // here.
Jim Grosbach871dff72011-10-11 15:59:20 +00001313 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1314 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001315 }
Jim Grosbach871dff72011-10-11 15:59:20 +00001316 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1317 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001318 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001319 }
1320
Jim Grosbachcd17c122011-08-04 23:01:30 +00001321 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1322 assert(N == 2 && "Invalid number of operands!");
1323 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1324 assert(CE && "non-constant AM2OffsetImm operand!");
1325 int32_t Val = CE->getValue();
1326 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1327 // Special case for #-0
1328 if (Val == INT32_MIN) Val = 0;
1329 if (Val < 0) Val = -Val;
1330 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1331 Inst.addOperand(MCOperand::CreateReg(0));
1332 Inst.addOperand(MCOperand::CreateImm(Val));
1333 }
1334
Jim Grosbach5b96b802011-08-10 20:29:19 +00001335 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1336 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001337 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1338 if (!Memory.OffsetRegNum) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00001339 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1340 // Special case for #-0
1341 if (Val == INT32_MIN) Val = 0;
1342 if (Val < 0) Val = -Val;
1343 Val = ARM_AM::getAM3Opc(AddSub, Val);
1344 } else {
1345 // For register offset, we encode the shift type and negation flag
1346 // here.
Jim Grosbach871dff72011-10-11 15:59:20 +00001347 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach5b96b802011-08-10 20:29:19 +00001348 }
Jim Grosbach871dff72011-10-11 15:59:20 +00001349 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1350 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach5b96b802011-08-10 20:29:19 +00001351 Inst.addOperand(MCOperand::CreateImm(Val));
1352 }
1353
1354 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1355 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001356 if (Kind == k_PostIndexRegister) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00001357 int32_t Val =
1358 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1359 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1360 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001361 return;
Jim Grosbach5b96b802011-08-10 20:29:19 +00001362 }
1363
1364 // Constant offset.
1365 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1366 int32_t Val = CE->getValue();
1367 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1368 // Special case for #-0
1369 if (Val == INT32_MIN) Val = 0;
1370 if (Val < 0) Val = -Val;
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001371 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach5b96b802011-08-10 20:29:19 +00001372 Inst.addOperand(MCOperand::CreateReg(0));
1373 Inst.addOperand(MCOperand::CreateImm(Val));
1374 }
1375
Jim Grosbachd3595712011-08-03 23:50:40 +00001376 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1377 assert(N == 2 && "Invalid number of operands!");
1378 // The lower two bits are always zero and as such are not encoded.
Jim Grosbach871dff72011-10-11 15:59:20 +00001379 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00001380 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1381 // Special case for #-0
1382 if (Val == INT32_MIN) Val = 0;
1383 if (Val < 0) Val = -Val;
1384 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbach871dff72011-10-11 15:59:20 +00001385 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001386 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00001387 }
1388
Jim Grosbach7db8d692011-09-08 22:07:06 +00001389 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1390 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001391 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1392 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7db8d692011-09-08 22:07:06 +00001393 Inst.addOperand(MCOperand::CreateImm(Val));
1394 }
1395
Jim Grosbacha05627e2011-09-09 18:37:27 +00001396 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1397 assert(N == 2 && "Invalid number of operands!");
1398 // The lower two bits are always zero and as such are not encoded.
Jim Grosbach871dff72011-10-11 15:59:20 +00001399 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1400 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha05627e2011-09-09 18:37:27 +00001401 Inst.addOperand(MCOperand::CreateImm(Val));
1402 }
1403
Jim Grosbachd3595712011-08-03 23:50:40 +00001404 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1405 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001406 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1407 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001408 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner5d6f6a02010-10-29 00:27:31 +00001409 }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001410
Jim Grosbach2392c532011-09-07 23:39:14 +00001411 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1412 addMemImm8OffsetOperands(Inst, N);
1413 }
1414
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001415 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach2392c532011-09-07 23:39:14 +00001416 addMemImm8OffsetOperands(Inst, N);
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001417 }
1418
1419 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1420 assert(N == 2 && "Invalid number of operands!");
1421 // If this is an immediate, it's a label reference.
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001422 if (Kind == k_Immediate) {
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001423 addExpr(Inst, getImm());
1424 Inst.addOperand(MCOperand::CreateImm(0));
1425 return;
1426 }
1427
1428 // Otherwise, it's a normal memory reg+offset.
Jim Grosbach871dff72011-10-11 15:59:20 +00001429 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1430 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001431 Inst.addOperand(MCOperand::CreateImm(Val));
1432 }
1433
Jim Grosbachd3595712011-08-03 23:50:40 +00001434 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1435 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach95466ce2011-08-08 20:59:31 +00001436 // If this is an immediate, it's a label reference.
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001437 if (Kind == k_Immediate) {
Jim Grosbach95466ce2011-08-08 20:59:31 +00001438 addExpr(Inst, getImm());
1439 Inst.addOperand(MCOperand::CreateImm(0));
1440 return;
1441 }
1442
1443 // Otherwise, it's a normal memory reg+offset.
Jim Grosbach871dff72011-10-11 15:59:20 +00001444 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1445 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001446 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendling092a7bd2010-12-14 03:36:38 +00001447 }
Bill Wendling811c9362010-11-30 07:44:32 +00001448
Jim Grosbach05541f42011-09-19 22:21:13 +00001449 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1450 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001451 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1452 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach05541f42011-09-19 22:21:13 +00001453 }
1454
1455 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1456 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001457 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1458 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach05541f42011-09-19 22:21:13 +00001459 }
1460
Jim Grosbachd3595712011-08-03 23:50:40 +00001461 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1462 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001463 unsigned Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1464 Memory.ShiftImm, Memory.ShiftType);
1465 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1466 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001467 Inst.addOperand(MCOperand::CreateImm(Val));
1468 }
1469
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001470 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1471 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001472 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1473 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1474 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001475 }
1476
Jim Grosbachd3595712011-08-03 23:50:40 +00001477 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1478 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001479 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1480 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001481 }
1482
Jim Grosbach3fe94e32011-08-19 17:55:24 +00001483 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1484 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001485 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1486 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach3fe94e32011-08-19 17:55:24 +00001487 Inst.addOperand(MCOperand::CreateImm(Val));
1488 }
1489
Jim Grosbach26d35872011-08-19 18:55:51 +00001490 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1491 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001492 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1493 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach26d35872011-08-19 18:55:51 +00001494 Inst.addOperand(MCOperand::CreateImm(Val));
1495 }
1496
Jim Grosbacha32c7532011-08-19 18:49:59 +00001497 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1498 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001499 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1500 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha32c7532011-08-19 18:49:59 +00001501 Inst.addOperand(MCOperand::CreateImm(Val));
1502 }
1503
Jim Grosbach23983d62011-08-19 18:13:48 +00001504 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1505 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001506 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1507 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach23983d62011-08-19 18:13:48 +00001508 Inst.addOperand(MCOperand::CreateImm(Val));
1509 }
1510
Jim Grosbachd3595712011-08-03 23:50:40 +00001511 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1512 assert(N == 1 && "Invalid number of operands!");
1513 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1514 assert(CE && "non-constant post-idx-imm8 operand!");
1515 int Imm = CE->getValue();
1516 bool isAdd = Imm >= 0;
Owen Andersonf02d98d2011-08-29 17:17:09 +00001517 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00001518 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1519 Inst.addOperand(MCOperand::CreateImm(Imm));
1520 }
1521
Jim Grosbach93981412011-10-11 21:55:36 +00001522 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1523 assert(N == 1 && "Invalid number of operands!");
1524 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1525 assert(CE && "non-constant post-idx-imm8s4 operand!");
1526 int Imm = CE->getValue();
1527 bool isAdd = Imm >= 0;
1528 if (Imm == INT32_MIN) Imm = 0;
1529 // Immediate is scaled by 4.
1530 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1531 Inst.addOperand(MCOperand::CreateImm(Imm));
1532 }
1533
Jim Grosbachd3595712011-08-03 23:50:40 +00001534 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1535 assert(N == 2 && "Invalid number of operands!");
1536 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachc320c852011-08-05 21:28:30 +00001537 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1538 }
1539
1540 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1541 assert(N == 2 && "Invalid number of operands!");
1542 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1543 // The sign, shift type, and shift amount are encoded in a single operand
1544 // using the AM2 encoding helpers.
1545 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1546 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1547 PostIdxReg.ShiftTy);
1548 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendling811c9362010-11-30 07:44:32 +00001549 }
1550
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001551 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1552 assert(N == 1 && "Invalid number of operands!");
1553 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1554 }
1555
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001556 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1557 assert(N == 1 && "Invalid number of operands!");
1558 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1559 }
1560
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001561 void addVecListOneDOperands(MCInst &Inst, unsigned N) const {
1562 assert(N == 1 && "Invalid number of operands!");
1563 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1564 }
1565
Jim Grosbach2f2e3c42011-10-21 18:54:25 +00001566 void addVecListTwoDOperands(MCInst &Inst, unsigned N) const {
1567 assert(N == 1 && "Invalid number of operands!");
1568 // Only the first register actually goes on the instruction. The rest
1569 // are implied by the opcode.
1570 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1571 }
1572
Jim Grosbachc4360fe2011-10-21 20:02:19 +00001573 void addVecListThreeDOperands(MCInst &Inst, unsigned N) const {
1574 assert(N == 1 && "Invalid number of operands!");
1575 // Only the first register actually goes on the instruction. The rest
1576 // are implied by the opcode.
1577 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1578 }
1579
Jim Grosbach846bcff2011-10-21 20:35:01 +00001580 void addVecListFourDOperands(MCInst &Inst, unsigned N) const {
1581 assert(N == 1 && "Invalid number of operands!");
1582 // Only the first register actually goes on the instruction. The rest
1583 // are implied by the opcode.
1584 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1585 }
1586
Jim Grosbach118b38c2011-10-21 22:21:10 +00001587 void addVecListTwoQOperands(MCInst &Inst, unsigned N) const {
1588 assert(N == 1 && "Invalid number of operands!");
1589 // Only the first register actually goes on the instruction. The rest
1590 // are implied by the opcode.
1591 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1592 }
1593
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001594 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1595 assert(N == 1 && "Invalid number of operands!");
1596 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1597 }
1598
1599 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1600 assert(N == 1 && "Invalid number of operands!");
1601 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1602 }
1603
1604 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1605 assert(N == 1 && "Invalid number of operands!");
1606 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1607 }
1608
Jim Grosbach741cd732011-10-17 22:26:03 +00001609 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1610 assert(N == 1 && "Invalid number of operands!");
1611 // The immediate encodes the type of constant as well as the value.
1612 // Mask in that this is an i8 splat.
1613 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1614 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1615 }
1616
Jim Grosbachcda32ae2011-10-17 23:09:09 +00001617 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1618 assert(N == 1 && "Invalid number of operands!");
1619 // The immediate encodes the type of constant as well as the value.
1620 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1621 unsigned Value = CE->getValue();
1622 if (Value >= 256)
1623 Value = (Value >> 8) | 0xa00;
1624 else
1625 Value |= 0x800;
1626 Inst.addOperand(MCOperand::CreateImm(Value));
1627 }
1628
Jim Grosbach8211c052011-10-18 00:22:00 +00001629 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1630 assert(N == 1 && "Invalid number of operands!");
1631 // The immediate encodes the type of constant as well as the value.
1632 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1633 unsigned Value = CE->getValue();
1634 if (Value >= 256 && Value <= 0xff00)
1635 Value = (Value >> 8) | 0x200;
1636 else if (Value > 0xffff && Value <= 0xff0000)
1637 Value = (Value >> 16) | 0x400;
1638 else if (Value > 0xffffff)
1639 Value = (Value >> 24) | 0x600;
1640 Inst.addOperand(MCOperand::CreateImm(Value));
1641 }
1642
1643 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1644 assert(N == 1 && "Invalid number of operands!");
1645 // The immediate encodes the type of constant as well as the value.
1646 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1647 unsigned Value = CE->getValue();
1648 if (Value >= 256 && Value <= 0xffff)
1649 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1650 else if (Value > 0xffff && Value <= 0xffffff)
1651 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1652 else if (Value > 0xffffff)
1653 Value = (Value >> 24) | 0x600;
1654 Inst.addOperand(MCOperand::CreateImm(Value));
1655 }
1656
Jim Grosbache4454e02011-10-18 16:18:11 +00001657 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1658 assert(N == 1 && "Invalid number of operands!");
1659 // The immediate encodes the type of constant as well as the value.
1660 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1661 uint64_t Value = CE->getValue();
1662 unsigned Imm = 0;
1663 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1664 Imm |= (Value & 1) << i;
1665 }
1666 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1667 }
1668
Jim Grosbach602aa902011-07-13 15:34:57 +00001669 virtual void print(raw_ostream &OS) const;
Daniel Dunbarebace222010-08-11 06:37:04 +00001670
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001671 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001672 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001673 Op->ITMask.Mask = Mask;
1674 Op->StartLoc = S;
1675 Op->EndLoc = S;
1676 return Op;
1677 }
1678
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001679 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001680 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001681 Op->CC.Val = CC;
1682 Op->StartLoc = S;
1683 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001684 return Op;
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001685 }
1686
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001687 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001688 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001689 Op->Cop.Val = CopVal;
1690 Op->StartLoc = S;
1691 Op->EndLoc = S;
1692 return Op;
1693 }
1694
1695 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001696 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001697 Op->Cop.Val = CopVal;
1698 Op->StartLoc = S;
1699 Op->EndLoc = S;
1700 return Op;
1701 }
1702
Jim Grosbach48399582011-10-12 17:34:41 +00001703 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1704 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1705 Op->Cop.Val = Val;
1706 Op->StartLoc = S;
1707 Op->EndLoc = E;
1708 return Op;
1709 }
1710
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001711 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001712 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001713 Op->Reg.RegNum = RegNum;
1714 Op->StartLoc = S;
1715 Op->EndLoc = S;
1716 return Op;
1717 }
1718
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001719 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001720 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001721 Op->Tok.Data = Str.data();
1722 Op->Tok.Length = Str.size();
1723 Op->StartLoc = S;
1724 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001725 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001726 }
1727
Bill Wendling2063b842010-11-18 23:43:05 +00001728 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001729 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001730 Op->Reg.RegNum = RegNum;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001731 Op->StartLoc = S;
1732 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001733 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001734 }
1735
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001736 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1737 unsigned SrcReg,
1738 unsigned ShiftReg,
1739 unsigned ShiftImm,
1740 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001741 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachac798e12011-07-25 20:49:51 +00001742 Op->RegShiftedReg.ShiftTy = ShTy;
1743 Op->RegShiftedReg.SrcReg = SrcReg;
1744 Op->RegShiftedReg.ShiftReg = ShiftReg;
1745 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001746 Op->StartLoc = S;
1747 Op->EndLoc = E;
1748 return Op;
1749 }
1750
Owen Andersonb595ed02011-07-21 18:54:16 +00001751 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1752 unsigned SrcReg,
1753 unsigned ShiftImm,
1754 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001755 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachac798e12011-07-25 20:49:51 +00001756 Op->RegShiftedImm.ShiftTy = ShTy;
1757 Op->RegShiftedImm.SrcReg = SrcReg;
1758 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Andersonb595ed02011-07-21 18:54:16 +00001759 Op->StartLoc = S;
1760 Op->EndLoc = E;
1761 return Op;
1762 }
1763
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001764 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001765 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001766 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001767 Op->ShifterImm.isASR = isASR;
1768 Op->ShifterImm.Imm = Imm;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001769 Op->StartLoc = S;
1770 Op->EndLoc = E;
1771 return Op;
1772 }
1773
Jim Grosbach833b9d32011-07-27 20:15:40 +00001774 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001775 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach833b9d32011-07-27 20:15:40 +00001776 Op->RotImm.Imm = Imm;
1777 Op->StartLoc = S;
1778 Op->EndLoc = E;
1779 return Op;
1780 }
1781
Jim Grosbach864b6092011-07-28 21:34:26 +00001782 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1783 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001784 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach864b6092011-07-28 21:34:26 +00001785 Op->Bitfield.LSB = LSB;
1786 Op->Bitfield.Width = Width;
1787 Op->StartLoc = S;
1788 Op->EndLoc = E;
1789 return Op;
1790 }
1791
Bill Wendling2cae3272010-11-09 22:44:22 +00001792 static ARMOperand *
Bill Wendlingbed94652010-11-09 23:28:44 +00001793 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00001794 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001795 KindTy Kind = k_RegisterList;
Bill Wendling9898ac92010-11-17 04:32:08 +00001796
Jim Grosbach75461af2011-09-13 22:56:44 +00001797 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001798 Kind = k_DPRRegisterList;
Jim Grosbach75461af2011-09-13 22:56:44 +00001799 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng9eec7642011-07-25 21:32:49 +00001800 contains(Regs.front().first))
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001801 Kind = k_SPRRegisterList;
Bill Wendling9898ac92010-11-17 04:32:08 +00001802
1803 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendlingbed94652010-11-09 23:28:44 +00001804 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00001805 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling0ab0f672010-11-18 21:50:54 +00001806 Op->Registers.push_back(I->first);
Bill Wendling20b5ea982010-11-19 00:38:19 +00001807 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00001808 Op->StartLoc = StartLoc;
1809 Op->EndLoc = EndLoc;
Bill Wendling7cef4472010-11-06 19:56:04 +00001810 return Op;
1811 }
1812
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001813 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
1814 SMLoc S, SMLoc E) {
1815 ARMOperand *Op = new ARMOperand(k_VectorList);
1816 Op->VectorList.RegNum = RegNum;
1817 Op->VectorList.Count = Count;
1818 Op->StartLoc = S;
1819 Op->EndLoc = E;
1820 return Op;
1821 }
1822
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001823 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
1824 MCContext &Ctx) {
1825 ARMOperand *Op = new ARMOperand(k_VectorIndex);
1826 Op->VectorIndex.Val = Idx;
1827 Op->StartLoc = S;
1828 Op->EndLoc = E;
1829 return Op;
1830 }
1831
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001832 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001833 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001834 Op->Imm.Val = Val;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001835 Op->StartLoc = S;
1836 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001837 return Op;
Kevin Enderbyf5079942009-10-13 22:19:02 +00001838 }
1839
Jim Grosbache7fbce72011-10-03 23:38:36 +00001840 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001841 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbache7fbce72011-10-03 23:38:36 +00001842 Op->FPImm.Val = Val;
1843 Op->StartLoc = S;
1844 Op->EndLoc = S;
1845 return Op;
1846 }
1847
Jim Grosbachd3595712011-08-03 23:50:40 +00001848 static ARMOperand *CreateMem(unsigned BaseRegNum,
1849 const MCConstantExpr *OffsetImm,
1850 unsigned OffsetRegNum,
1851 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00001852 unsigned ShiftImm,
Jim Grosbacha95ec992011-10-11 17:29:55 +00001853 unsigned Alignment,
Jim Grosbachd3595712011-08-03 23:50:40 +00001854 bool isNegative,
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001855 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001856 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbach871dff72011-10-11 15:59:20 +00001857 Op->Memory.BaseRegNum = BaseRegNum;
1858 Op->Memory.OffsetImm = OffsetImm;
1859 Op->Memory.OffsetRegNum = OffsetRegNum;
1860 Op->Memory.ShiftType = ShiftType;
1861 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbacha95ec992011-10-11 17:29:55 +00001862 Op->Memory.Alignment = Alignment;
Jim Grosbach871dff72011-10-11 15:59:20 +00001863 Op->Memory.isNegative = isNegative;
Jim Grosbachd3595712011-08-03 23:50:40 +00001864 Op->StartLoc = S;
1865 Op->EndLoc = E;
1866 return Op;
1867 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00001868
Jim Grosbachc320c852011-08-05 21:28:30 +00001869 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
1870 ARM_AM::ShiftOpc ShiftTy,
1871 unsigned ShiftImm,
Jim Grosbachd3595712011-08-03 23:50:40 +00001872 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001873 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbachd3595712011-08-03 23:50:40 +00001874 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachc320c852011-08-05 21:28:30 +00001875 Op->PostIdxReg.isAdd = isAdd;
1876 Op->PostIdxReg.ShiftTy = ShiftTy;
1877 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001878 Op->StartLoc = S;
1879 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001880 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001881 }
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001882
1883 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001884 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001885 Op->MBOpt.Val = Opt;
1886 Op->StartLoc = S;
1887 Op->EndLoc = S;
1888 return Op;
1889 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001890
1891 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001892 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001893 Op->IFlags.Val = IFlags;
1894 Op->StartLoc = S;
1895 Op->EndLoc = S;
1896 return Op;
1897 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001898
1899 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001900 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001901 Op->MMask.Val = MMask;
1902 Op->StartLoc = S;
1903 Op->EndLoc = S;
1904 return Op;
1905 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001906};
1907
1908} // end anonymous namespace.
1909
Jim Grosbach602aa902011-07-13 15:34:57 +00001910void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001911 switch (Kind) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001912 case k_FPImmediate:
Jim Grosbache7fbce72011-10-03 23:38:36 +00001913 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
1914 << ") >";
1915 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001916 case k_CondCode:
Daniel Dunbar2be732a2011-01-10 15:26:21 +00001917 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001918 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001919 case k_CCOut:
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001920 OS << "<ccout " << getReg() << ">";
1921 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001922 case k_ITCondMask: {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00001923 static const char *MaskStr[] = {
1924 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
1925 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
1926 };
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001927 assert((ITMask.Mask & 0xf) == ITMask.Mask);
1928 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
1929 break;
1930 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001931 case k_CoprocNum:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001932 OS << "<coprocessor number: " << getCoproc() << ">";
1933 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001934 case k_CoprocReg:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001935 OS << "<coprocessor register: " << getCoproc() << ">";
1936 break;
Jim Grosbach48399582011-10-12 17:34:41 +00001937 case k_CoprocOption:
1938 OS << "<coprocessor option: " << CoprocOption.Val << ">";
1939 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001940 case k_MSRMask:
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001941 OS << "<mask: " << getMSRMask() << ">";
1942 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001943 case k_Immediate:
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001944 getImm()->print(OS);
1945 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001946 case k_MemBarrierOpt:
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001947 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
1948 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001949 case k_Memory:
Daniel Dunbarbcd8eb02011-01-18 05:55:21 +00001950 OS << "<memory "
Jim Grosbach871dff72011-10-11 15:59:20 +00001951 << " base:" << Memory.BaseRegNum;
Daniel Dunbarbcd8eb02011-01-18 05:55:21 +00001952 OS << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001953 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001954 case k_PostIndexRegister:
Jim Grosbachc320c852011-08-05 21:28:30 +00001955 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
1956 << PostIdxReg.RegNum;
1957 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
1958 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
1959 << PostIdxReg.ShiftImm;
1960 OS << ">";
Jim Grosbachd3595712011-08-03 23:50:40 +00001961 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001962 case k_ProcIFlags: {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001963 OS << "<ARM_PROC::";
1964 unsigned IFlags = getProcIFlags();
1965 for (int i=2; i >= 0; --i)
1966 if (IFlags & (1 << i))
1967 OS << ARM_PROC::IFlagsToString(1 << i);
1968 OS << ">";
1969 break;
1970 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001971 case k_Register:
Bill Wendling2063b842010-11-18 23:43:05 +00001972 OS << "<register " << getReg() << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001973 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001974 case k_ShifterImmediate:
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001975 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
1976 << " #" << ShifterImm.Imm << ">";
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001977 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001978 case k_ShiftedRegister:
Owen Andersonb595ed02011-07-21 18:54:16 +00001979 OS << "<so_reg_reg "
Jim Grosbachac798e12011-07-25 20:49:51 +00001980 << RegShiftedReg.SrcReg
1981 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedReg.ShiftImm))
1982 << ", " << RegShiftedReg.ShiftReg << ", "
1983 << ARM_AM::getSORegOffset(RegShiftedReg.ShiftImm)
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001984 << ">";
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001985 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001986 case k_ShiftedImmediate:
Owen Andersonb595ed02011-07-21 18:54:16 +00001987 OS << "<so_reg_imm "
Jim Grosbachac798e12011-07-25 20:49:51 +00001988 << RegShiftedImm.SrcReg
1989 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedImm.ShiftImm))
1990 << ", " << ARM_AM::getSORegOffset(RegShiftedImm.ShiftImm)
Owen Andersonb595ed02011-07-21 18:54:16 +00001991 << ">";
1992 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001993 case k_RotateImmediate:
Jim Grosbach833b9d32011-07-27 20:15:40 +00001994 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
1995 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001996 case k_BitfieldDescriptor:
Jim Grosbach864b6092011-07-28 21:34:26 +00001997 OS << "<bitfield " << "lsb: " << Bitfield.LSB
1998 << ", width: " << Bitfield.Width << ">";
1999 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002000 case k_RegisterList:
2001 case k_DPRRegisterList:
2002 case k_SPRRegisterList: {
Bill Wendling7cef4472010-11-06 19:56:04 +00002003 OS << "<register_list ";
Bill Wendling7cef4472010-11-06 19:56:04 +00002004
Bill Wendlingbed94652010-11-09 23:28:44 +00002005 const SmallVectorImpl<unsigned> &RegList = getRegList();
2006 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00002007 I = RegList.begin(), E = RegList.end(); I != E; ) {
2008 OS << *I;
2009 if (++I < E) OS << ", ";
Bill Wendling7cef4472010-11-06 19:56:04 +00002010 }
2011
2012 OS << ">";
2013 break;
2014 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002015 case k_VectorList:
2016 OS << "<vector_list " << VectorList.Count << " * "
2017 << VectorList.RegNum << ">";
2018 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002019 case k_Token:
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002020 OS << "'" << getToken() << "'";
2021 break;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002022 case k_VectorIndex:
2023 OS << "<vectorindex " << getVectorIndex() << ">";
2024 break;
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002025 }
2026}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00002027
2028/// @name Auto-generated Match Functions
2029/// {
2030
2031static unsigned MatchRegisterName(StringRef Name);
2032
2033/// }
2034
Bob Wilsonfb0bd042011-02-03 21:46:10 +00002035bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2036 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002037 RegNo = tryParseRegister();
Roman Divacky36b1b472011-01-27 17:14:22 +00002038
2039 return (RegNo == (unsigned)-1);
2040}
2041
Kevin Enderby8be42bd2009-10-30 22:55:57 +00002042/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattner44e5981c2010-10-30 04:09:10 +00002043/// and if it is a register name the token is eaten and the register number is
2044/// returned. Otherwise return -1.
2045///
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002046int ARMAsmParser::tryParseRegister() {
Chris Lattner44e5981c2010-10-30 04:09:10 +00002047 const AsmToken &Tok = Parser.getTok();
Jim Grosbachd3595712011-08-03 23:50:40 +00002048 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbach99710a82010-11-01 16:44:21 +00002049
Chris Lattner44e5981c2010-10-30 04:09:10 +00002050 // FIXME: Validate register for the current architecture; we have to do
2051 // validation later, so maybe there is no need for this here.
Owen Andersona098d152011-01-13 22:50:36 +00002052 std::string upperCase = Tok.getString().str();
2053 std::string lowerCase = LowercaseString(upperCase);
2054 unsigned RegNum = MatchRegisterName(lowerCase);
2055 if (!RegNum) {
2056 RegNum = StringSwitch<unsigned>(lowerCase)
2057 .Case("r13", ARM::SP)
2058 .Case("r14", ARM::LR)
2059 .Case("r15", ARM::PC)
2060 .Case("ip", ARM::R12)
2061 .Default(0);
2062 }
2063 if (!RegNum) return -1;
Bob Wilsonfb0bd042011-02-03 21:46:10 +00002064
Chris Lattner44e5981c2010-10-30 04:09:10 +00002065 Parser.Lex(); // Eat identifier token.
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002066
Chris Lattner44e5981c2010-10-30 04:09:10 +00002067 return RegNum;
2068}
Jim Grosbach99710a82010-11-01 16:44:21 +00002069
Jim Grosbachbb24c592011-07-13 18:49:30 +00002070// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2071// If a recoverable error occurs, return 1. If an irrecoverable error
2072// occurs, return -1. An irrecoverable error is one where tokens have been
2073// consumed in the process of trying to parse the shifter (i.e., when it is
2074// indeed a shifter operand, but malformed).
Jim Grosbach0d6022d2011-07-26 20:41:24 +00002075int ARMAsmParser::tryParseShiftRegister(
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002076 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2077 SMLoc S = Parser.getTok().getLoc();
2078 const AsmToken &Tok = Parser.getTok();
2079 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2080
2081 std::string upperCase = Tok.getString().str();
2082 std::string lowerCase = LowercaseString(upperCase);
2083 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
2084 .Case("lsl", ARM_AM::lsl)
2085 .Case("lsr", ARM_AM::lsr)
2086 .Case("asr", ARM_AM::asr)
2087 .Case("ror", ARM_AM::ror)
2088 .Case("rrx", ARM_AM::rrx)
2089 .Default(ARM_AM::no_shift);
2090
2091 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbachbb24c592011-07-13 18:49:30 +00002092 return 1;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002093
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002094 Parser.Lex(); // Eat the operator.
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002095
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002096 // The source register for the shift has already been added to the
2097 // operand list, so we need to pop it off and combine it into the shifted
2098 // register operand instead.
Benjamin Kramer1757e7a2011-07-14 18:41:22 +00002099 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002100 if (!PrevOp->isReg())
2101 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2102 int SrcReg = PrevOp->getReg();
2103 int64_t Imm = 0;
2104 int ShiftReg = 0;
2105 if (ShiftTy == ARM_AM::rrx) {
2106 // RRX Doesn't have an explicit shift amount. The encoder expects
2107 // the shift register to be the same as the source register. Seems odd,
2108 // but OK.
2109 ShiftReg = SrcReg;
2110 } else {
2111 // Figure out if this is shifted by a constant or a register (for non-RRX).
2112 if (Parser.getTok().is(AsmToken::Hash)) {
2113 Parser.Lex(); // Eat hash.
2114 SMLoc ImmLoc = Parser.getTok().getLoc();
2115 const MCExpr *ShiftExpr = 0;
Jim Grosbachbb24c592011-07-13 18:49:30 +00002116 if (getParser().ParseExpression(ShiftExpr)) {
2117 Error(ImmLoc, "invalid immediate shift value");
2118 return -1;
2119 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002120 // The expression must be evaluatable as an immediate.
2121 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbachbb24c592011-07-13 18:49:30 +00002122 if (!CE) {
2123 Error(ImmLoc, "invalid immediate shift value");
2124 return -1;
2125 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002126 // Range check the immediate.
2127 // lsl, ror: 0 <= imm <= 31
2128 // lsr, asr: 0 <= imm <= 32
2129 Imm = CE->getValue();
2130 if (Imm < 0 ||
2131 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2132 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbachbb24c592011-07-13 18:49:30 +00002133 Error(ImmLoc, "immediate shift value out of range");
2134 return -1;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002135 }
2136 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002137 ShiftReg = tryParseRegister();
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002138 SMLoc L = Parser.getTok().getLoc();
Jim Grosbachbb24c592011-07-13 18:49:30 +00002139 if (ShiftReg == -1) {
2140 Error (L, "expected immediate or register in shift operand");
2141 return -1;
2142 }
2143 } else {
2144 Error (Parser.getTok().getLoc(),
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002145 "expected immediate or register in shift operand");
Jim Grosbachbb24c592011-07-13 18:49:30 +00002146 return -1;
2147 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002148 }
2149
Owen Andersonb595ed02011-07-21 18:54:16 +00002150 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2151 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachac798e12011-07-25 20:49:51 +00002152 ShiftReg, Imm,
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002153 S, Parser.getTok().getLoc()));
Owen Andersonb595ed02011-07-21 18:54:16 +00002154 else
2155 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2156 S, Parser.getTok().getLoc()));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002157
Jim Grosbachbb24c592011-07-13 18:49:30 +00002158 return 0;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002159}
2160
2161
Bill Wendling2063b842010-11-18 23:43:05 +00002162/// Try to parse a register name. The token must be an Identifier when called.
2163/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2164/// if there is a "writeback". 'true' if it's not a register.
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002165///
Kevin Enderby8be42bd2009-10-30 22:55:57 +00002166/// TODO this is likely to change to allow different register types and or to
2167/// parse for a specific register type.
Bill Wendling2063b842010-11-18 23:43:05 +00002168bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002169tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattner44e5981c2010-10-30 04:09:10 +00002170 SMLoc S = Parser.getTok().getLoc();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002171 int RegNo = tryParseRegister();
Bill Wendlinge18980a2010-11-06 22:36:58 +00002172 if (RegNo == -1)
Bill Wendling2063b842010-11-18 23:43:05 +00002173 return true;
Jim Grosbach99710a82010-11-01 16:44:21 +00002174
Bill Wendling2063b842010-11-18 23:43:05 +00002175 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002176
Chris Lattner44e5981c2010-10-30 04:09:10 +00002177 const AsmToken &ExclaimTok = Parser.getTok();
2178 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling2063b842010-11-18 23:43:05 +00002179 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2180 ExclaimTok.getLoc()));
Chris Lattner44e5981c2010-10-30 04:09:10 +00002181 Parser.Lex(); // Eat exclaim token
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002182 return false;
2183 }
2184
2185 // Also check for an index operand. This is only legal for vector registers,
2186 // but that'll get caught OK in operand matching, so we don't need to
2187 // explicitly filter everything else out here.
2188 if (Parser.getTok().is(AsmToken::LBrac)) {
2189 SMLoc SIdx = Parser.getTok().getLoc();
2190 Parser.Lex(); // Eat left bracket token.
2191
2192 const MCExpr *ImmVal;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002193 if (getParser().ParseExpression(ImmVal))
2194 return MatchOperand_ParseFail;
2195 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2196 if (!MCE) {
2197 TokError("immediate value expected for vector index");
2198 return MatchOperand_ParseFail;
2199 }
2200
2201 SMLoc E = Parser.getTok().getLoc();
2202 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2203 Error(E, "']' expected");
2204 return MatchOperand_ParseFail;
2205 }
2206
2207 Parser.Lex(); // Eat right bracket token.
2208
2209 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2210 SIdx, E,
2211 getContext()));
Kevin Enderby2207e5f2009-10-07 18:01:35 +00002212 }
2213
Bill Wendling2063b842010-11-18 23:43:05 +00002214 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002215}
2216
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002217/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2218/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2219/// "c5", ...
2220static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002221 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2222 // but efficient.
2223 switch (Name.size()) {
2224 default: break;
2225 case 2:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002226 if (Name[0] != CoprocOp)
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002227 return -1;
2228 switch (Name[1]) {
2229 default: return -1;
2230 case '0': return 0;
2231 case '1': return 1;
2232 case '2': return 2;
2233 case '3': return 3;
2234 case '4': return 4;
2235 case '5': return 5;
2236 case '6': return 6;
2237 case '7': return 7;
2238 case '8': return 8;
2239 case '9': return 9;
2240 }
2241 break;
2242 case 3:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002243 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002244 return -1;
2245 switch (Name[2]) {
2246 default: return -1;
2247 case '0': return 10;
2248 case '1': return 11;
2249 case '2': return 12;
2250 case '3': return 13;
2251 case '4': return 14;
2252 case '5': return 15;
2253 }
2254 break;
2255 }
2256
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002257 return -1;
2258}
2259
Jim Grosbach3d1eac82011-08-26 21:43:41 +00002260/// parseITCondCode - Try to parse a condition code for an IT instruction.
2261ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2262parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2263 SMLoc S = Parser.getTok().getLoc();
2264 const AsmToken &Tok = Parser.getTok();
2265 if (!Tok.is(AsmToken::Identifier))
2266 return MatchOperand_NoMatch;
2267 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2268 .Case("eq", ARMCC::EQ)
2269 .Case("ne", ARMCC::NE)
2270 .Case("hs", ARMCC::HS)
2271 .Case("cs", ARMCC::HS)
2272 .Case("lo", ARMCC::LO)
2273 .Case("cc", ARMCC::LO)
2274 .Case("mi", ARMCC::MI)
2275 .Case("pl", ARMCC::PL)
2276 .Case("vs", ARMCC::VS)
2277 .Case("vc", ARMCC::VC)
2278 .Case("hi", ARMCC::HI)
2279 .Case("ls", ARMCC::LS)
2280 .Case("ge", ARMCC::GE)
2281 .Case("lt", ARMCC::LT)
2282 .Case("gt", ARMCC::GT)
2283 .Case("le", ARMCC::LE)
2284 .Case("al", ARMCC::AL)
2285 .Default(~0U);
2286 if (CC == ~0U)
2287 return MatchOperand_NoMatch;
2288 Parser.Lex(); // Eat the token.
2289
2290 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2291
2292 return MatchOperand_Success;
2293}
2294
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002295/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002296/// token must be an Identifier when called, and if it is a coprocessor
2297/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002298ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002299parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002300 SMLoc S = Parser.getTok().getLoc();
2301 const AsmToken &Tok = Parser.getTok();
Jim Grosbach54a20ed2011-10-12 20:54:17 +00002302 if (Tok.isNot(AsmToken::Identifier))
2303 return MatchOperand_NoMatch;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002304
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002305 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002306 if (Num == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002307 return MatchOperand_NoMatch;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002308
2309 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002310 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002311 return MatchOperand_Success;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002312}
2313
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002314/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002315/// token must be an Identifier when called, and if it is a coprocessor
2316/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002317ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002318parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002319 SMLoc S = Parser.getTok().getLoc();
2320 const AsmToken &Tok = Parser.getTok();
Jim Grosbach54a20ed2011-10-12 20:54:17 +00002321 if (Tok.isNot(AsmToken::Identifier))
2322 return MatchOperand_NoMatch;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002323
2324 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2325 if (Reg == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002326 return MatchOperand_NoMatch;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002327
2328 Parser.Lex(); // Eat identifier token.
2329 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002330 return MatchOperand_Success;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002331}
2332
Jim Grosbach48399582011-10-12 17:34:41 +00002333/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2334/// coproc_option : '{' imm0_255 '}'
2335ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2336parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2337 SMLoc S = Parser.getTok().getLoc();
2338
2339 // If this isn't a '{', this isn't a coprocessor immediate operand.
2340 if (Parser.getTok().isNot(AsmToken::LCurly))
2341 return MatchOperand_NoMatch;
2342 Parser.Lex(); // Eat the '{'
2343
2344 const MCExpr *Expr;
2345 SMLoc Loc = Parser.getTok().getLoc();
2346 if (getParser().ParseExpression(Expr)) {
2347 Error(Loc, "illegal expression");
2348 return MatchOperand_ParseFail;
2349 }
2350 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2351 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2352 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2353 return MatchOperand_ParseFail;
2354 }
2355 int Val = CE->getValue();
2356
2357 // Check for and consume the closing '}'
2358 if (Parser.getTok().isNot(AsmToken::RCurly))
2359 return MatchOperand_ParseFail;
2360 SMLoc E = Parser.getTok().getLoc();
2361 Parser.Lex(); // Eat the '}'
2362
2363 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2364 return MatchOperand_Success;
2365}
2366
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002367// For register list parsing, we need to map from raw GPR register numbering
2368// to the enumeration values. The enumeration values aren't sorted by
2369// register number due to our using "sp", "lr" and "pc" as canonical names.
2370static unsigned getNextRegister(unsigned Reg) {
2371 // If this is a GPR, we need to do it manually, otherwise we can rely
2372 // on the sort ordering of the enumeration since the other reg-classes
2373 // are sane.
2374 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2375 return Reg + 1;
2376 switch(Reg) {
2377 default: assert(0 && "Invalid GPR number!");
2378 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2379 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2380 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2381 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2382 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2383 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2384 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2385 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2386 }
2387}
2388
2389/// Parse a register list.
Bill Wendling2063b842010-11-18 23:43:05 +00002390bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002391parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan936b0d32010-01-19 21:44:56 +00002392 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00002393 "Token is not a Left Curly Brace");
Bill Wendlinge18980a2010-11-06 22:36:58 +00002394 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002395 Parser.Lex(); // Eat '{' token.
2396 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbya2b99102009-10-09 21:12:28 +00002397
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002398 // Check the first register in the list to see what register class
2399 // this is a list of.
2400 int Reg = tryParseRegister();
2401 if (Reg == -1)
2402 return Error(RegLoc, "register expected");
2403
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00002404 const MCRegisterClass *RC;
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002405 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2406 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2407 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2408 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2409 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2410 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2411 else
2412 return Error(RegLoc, "invalid register in register list");
2413
2414 // The reglist instructions have at most 16 registers, so reserve
2415 // space for that many.
Jim Grosbache3a6a822011-09-13 20:35:57 +00002416 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002417 // Store the first register.
2418 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbya2b99102009-10-09 21:12:28 +00002419
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002420 // This starts immediately after the first register token in the list,
2421 // so we can see either a comma or a minus (range separator) as a legal
2422 // next token.
2423 while (Parser.getTok().is(AsmToken::Comma) ||
2424 Parser.getTok().is(AsmToken::Minus)) {
2425 if (Parser.getTok().is(AsmToken::Minus)) {
2426 Parser.Lex(); // Eat the comma.
2427 SMLoc EndLoc = Parser.getTok().getLoc();
2428 int EndReg = tryParseRegister();
2429 if (EndReg == -1)
2430 return Error(EndLoc, "register expected");
2431 // If the register is the same as the start reg, there's nothing
2432 // more to do.
2433 if (Reg == EndReg)
2434 continue;
2435 // The register must be in the same register class as the first.
2436 if (!RC->contains(EndReg))
2437 return Error(EndLoc, "invalid register in register list");
2438 // Ranges must go from low to high.
2439 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2440 return Error(EndLoc, "bad range in register list");
Kevin Enderbya2b99102009-10-09 21:12:28 +00002441
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002442 // Add all the registers in the range to the register list.
2443 while (Reg != EndReg) {
2444 Reg = getNextRegister(Reg);
2445 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2446 }
2447 continue;
2448 }
2449 Parser.Lex(); // Eat the comma.
2450 RegLoc = Parser.getTok().getLoc();
2451 int OldReg = Reg;
2452 Reg = tryParseRegister();
2453 if (Reg == -1)
Jim Grosbach3337e392011-09-12 23:36:42 +00002454 return Error(RegLoc, "register expected");
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002455 // The register must be in the same register class as the first.
2456 if (!RC->contains(Reg))
2457 return Error(RegLoc, "invalid register in register list");
2458 // List must be monotonically increasing.
2459 if (getARMRegisterNumbering(Reg) <= getARMRegisterNumbering(OldReg))
2460 return Error(RegLoc, "register list not in ascending order");
2461 // VFP register lists must also be contiguous.
2462 // It's OK to use the enumeration values directly here rather, as the
2463 // VFP register classes have the enum sorted properly.
2464 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2465 Reg != OldReg + 1)
2466 return Error(RegLoc, "non-contiguous register range");
2467 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Bill Wendlinge18980a2010-11-06 22:36:58 +00002468 }
2469
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002470 SMLoc E = Parser.getTok().getLoc();
2471 if (Parser.getTok().isNot(AsmToken::RCurly))
2472 return Error(E, "'}' expected");
2473 Parser.Lex(); // Eat '}' token.
2474
Bill Wendling2063b842010-11-18 23:43:05 +00002475 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2476 return false;
Kevin Enderbya2b99102009-10-09 21:12:28 +00002477}
2478
Jim Grosbach080a4992011-10-28 00:06:50 +00002479// Return the low-subreg of a given Q register.
2480static unsigned getDRegFromQReg(unsigned QReg) {
2481 switch (QReg) {
2482 default: llvm_unreachable("expected a Q register!");
2483 case ARM::Q0: return ARM::D0;
2484 case ARM::Q1: return ARM::D2;
2485 case ARM::Q2: return ARM::D4;
2486 case ARM::Q3: return ARM::D6;
2487 case ARM::Q4: return ARM::D8;
2488 case ARM::Q5: return ARM::D10;
2489 case ARM::Q6: return ARM::D12;
2490 case ARM::Q7: return ARM::D14;
2491 case ARM::Q8: return ARM::D16;
2492 case ARM::Q9: return ARM::D19;
2493 case ARM::Q10: return ARM::D20;
2494 case ARM::Q11: return ARM::D22;
2495 case ARM::Q12: return ARM::D24;
2496 case ARM::Q13: return ARM::D26;
2497 case ARM::Q14: return ARM::D28;
2498 case ARM::Q15: return ARM::D30;
2499 }
2500}
2501
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002502// parse a vector register list
2503ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2504parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2505 if(Parser.getTok().isNot(AsmToken::LCurly))
2506 return MatchOperand_NoMatch;
2507
2508 SMLoc S = Parser.getTok().getLoc();
2509 Parser.Lex(); // Eat '{' token.
2510 SMLoc RegLoc = Parser.getTok().getLoc();
2511
2512 int Reg = tryParseRegister();
2513 if (Reg == -1) {
2514 Error(RegLoc, "register expected");
2515 return MatchOperand_ParseFail;
2516 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002517 unsigned Count = 1;
Jim Grosbach080a4992011-10-28 00:06:50 +00002518 unsigned FirstReg = Reg;
2519 // The list is of D registers, but we also allow Q regs and just interpret
2520 // them as the two D sub-registers.
2521 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2522 FirstReg = Reg = getDRegFromQReg(Reg);
2523 ++Reg;
2524 ++Count;
2525 }
2526
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002527 while (Parser.getTok().is(AsmToken::Comma)) {
2528 Parser.Lex(); // Eat the comma.
2529 RegLoc = Parser.getTok().getLoc();
2530 int OldReg = Reg;
2531 Reg = tryParseRegister();
2532 if (Reg == -1) {
2533 Error(RegLoc, "register expected");
2534 return MatchOperand_ParseFail;
2535 }
Jim Grosbach080a4992011-10-28 00:06:50 +00002536 // vector register lists must be contiguous.
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002537 // It's OK to use the enumeration values directly here rather, as the
2538 // VFP register classes have the enum sorted properly.
Jim Grosbach080a4992011-10-28 00:06:50 +00002539 //
2540 // The list is of D registers, but we also allow Q regs and just interpret
2541 // them as the two D sub-registers.
2542 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2543 Reg = getDRegFromQReg(Reg);
2544 if (Reg != OldReg + 1) {
2545 Error(RegLoc, "non-contiguous register range");
2546 return MatchOperand_ParseFail;
2547 }
2548 ++Reg;
2549 Count += 2;
2550 continue;
2551 }
2552 // Normal D register. Just check that it's contiguous and keep going.
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002553 if (Reg != OldReg + 1) {
2554 Error(RegLoc, "non-contiguous register range");
2555 return MatchOperand_ParseFail;
2556 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002557 ++Count;
2558 }
2559
2560 SMLoc E = Parser.getTok().getLoc();
2561 if (Parser.getTok().isNot(AsmToken::RCurly)) {
2562 Error(E, "'}' expected");
2563 return MatchOperand_ParseFail;
2564 }
2565 Parser.Lex(); // Eat '}' token.
2566
2567 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count, S, E));
2568 return MatchOperand_Success;
2569}
2570
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002571/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002572ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002573parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002574 SMLoc S = Parser.getTok().getLoc();
2575 const AsmToken &Tok = Parser.getTok();
2576 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2577 StringRef OptStr = Tok.getString();
2578
2579 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2580 .Case("sy", ARM_MB::SY)
2581 .Case("st", ARM_MB::ST)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002582 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002583 .Case("ish", ARM_MB::ISH)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002584 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002585 .Case("ishst", ARM_MB::ISHST)
2586 .Case("nsh", ARM_MB::NSH)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002587 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002588 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002589 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002590 .Case("osh", ARM_MB::OSH)
2591 .Case("oshst", ARM_MB::OSHST)
2592 .Default(~0U);
2593
2594 if (Opt == ~0U)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002595 return MatchOperand_NoMatch;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002596
2597 Parser.Lex(); // Eat identifier token.
2598 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002599 return MatchOperand_Success;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002600}
2601
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002602/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002603ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002604parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002605 SMLoc S = Parser.getTok().getLoc();
2606 const AsmToken &Tok = Parser.getTok();
2607 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2608 StringRef IFlagsStr = Tok.getString();
2609
Owen Anderson10c5b122011-10-05 17:16:40 +00002610 // An iflags string of "none" is interpreted to mean that none of the AIF
2611 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002612 unsigned IFlags = 0;
Owen Anderson10c5b122011-10-05 17:16:40 +00002613 if (IFlagsStr != "none") {
2614 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2615 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2616 .Case("a", ARM_PROC::A)
2617 .Case("i", ARM_PROC::I)
2618 .Case("f", ARM_PROC::F)
2619 .Default(~0U);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002620
Owen Anderson10c5b122011-10-05 17:16:40 +00002621 // If some specific iflag is already set, it means that some letter is
2622 // present more than once, this is not acceptable.
2623 if (Flag == ~0U || (IFlags & Flag))
2624 return MatchOperand_NoMatch;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002625
Owen Anderson10c5b122011-10-05 17:16:40 +00002626 IFlags |= Flag;
2627 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002628 }
2629
2630 Parser.Lex(); // Eat identifier token.
2631 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2632 return MatchOperand_Success;
2633}
2634
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002635/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002636ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002637parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002638 SMLoc S = Parser.getTok().getLoc();
2639 const AsmToken &Tok = Parser.getTok();
2640 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2641 StringRef Mask = Tok.getString();
2642
James Molloy21efa7d2011-09-28 14:21:38 +00002643 if (isMClass()) {
2644 // See ARMv6-M 10.1.1
2645 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2646 .Case("apsr", 0)
2647 .Case("iapsr", 1)
2648 .Case("eapsr", 2)
2649 .Case("xpsr", 3)
2650 .Case("ipsr", 5)
2651 .Case("epsr", 6)
2652 .Case("iepsr", 7)
2653 .Case("msp", 8)
2654 .Case("psp", 9)
2655 .Case("primask", 16)
2656 .Case("basepri", 17)
2657 .Case("basepri_max", 18)
2658 .Case("faultmask", 19)
2659 .Case("control", 20)
2660 .Default(~0U);
2661
2662 if (FlagsVal == ~0U)
2663 return MatchOperand_NoMatch;
2664
2665 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
2666 // basepri, basepri_max and faultmask only valid for V7m.
2667 return MatchOperand_NoMatch;
2668
2669 Parser.Lex(); // Eat identifier token.
2670 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2671 return MatchOperand_Success;
2672 }
2673
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002674 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
2675 size_t Start = 0, Next = Mask.find('_');
2676 StringRef Flags = "";
Jim Grosbachd25c2cd2011-07-19 22:45:10 +00002677 std::string SpecReg = LowercaseString(Mask.slice(Start, Next));
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002678 if (Next != StringRef::npos)
2679 Flags = Mask.slice(Next+1, Mask.size());
2680
2681 // FlagsVal contains the complete mask:
2682 // 3-0: Mask
2683 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2684 unsigned FlagsVal = 0;
2685
2686 if (SpecReg == "apsr") {
2687 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachd25c2cd2011-07-19 22:45:10 +00002688 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002689 .Case("g", 0x4) // same as CPSR_s
2690 .Case("nzcvqg", 0xc) // same as CPSR_fs
2691 .Default(~0U);
2692
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00002693 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002694 if (!Flags.empty())
2695 return MatchOperand_NoMatch;
2696 else
Jim Grosbach0ecd3952011-09-14 20:03:46 +00002697 FlagsVal = 8; // No flag
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00002698 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002699 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes54452132011-05-25 00:35:03 +00002700 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
2701 Flags = "fc";
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002702 for (int i = 0, e = Flags.size(); i != e; ++i) {
2703 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
2704 .Case("c", 1)
2705 .Case("x", 2)
2706 .Case("s", 4)
2707 .Case("f", 8)
2708 .Default(~0U);
2709
2710 // If some specific flag is already set, it means that some letter is
2711 // present more than once, this is not acceptable.
2712 if (FlagsVal == ~0U || (FlagsVal & Flag))
2713 return MatchOperand_NoMatch;
2714 FlagsVal |= Flag;
2715 }
2716 } else // No match for special register.
2717 return MatchOperand_NoMatch;
2718
Owen Anderson03a173e2011-10-21 18:43:28 +00002719 // Special register without flags is NOT equivalent to "fc" flags.
2720 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
2721 // two lines would enable gas compatibility at the expense of breaking
2722 // round-tripping.
2723 //
2724 // if (!FlagsVal)
2725 // FlagsVal = 0x9;
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002726
2727 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2728 if (SpecReg == "spsr")
2729 FlagsVal |= 16;
2730
2731 Parser.Lex(); // Eat identifier token.
2732 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2733 return MatchOperand_Success;
2734}
2735
Jim Grosbach27c1e252011-07-21 17:23:04 +00002736ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2737parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
2738 int Low, int High) {
2739 const AsmToken &Tok = Parser.getTok();
2740 if (Tok.isNot(AsmToken::Identifier)) {
2741 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2742 return MatchOperand_ParseFail;
2743 }
2744 StringRef ShiftName = Tok.getString();
2745 std::string LowerOp = LowercaseString(Op);
2746 std::string UpperOp = UppercaseString(Op);
2747 if (ShiftName != LowerOp && ShiftName != UpperOp) {
2748 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2749 return MatchOperand_ParseFail;
2750 }
2751 Parser.Lex(); // Eat shift type token.
2752
2753 // There must be a '#' and a shift amount.
2754 if (Parser.getTok().isNot(AsmToken::Hash)) {
2755 Error(Parser.getTok().getLoc(), "'#' expected");
2756 return MatchOperand_ParseFail;
2757 }
2758 Parser.Lex(); // Eat hash token.
2759
2760 const MCExpr *ShiftAmount;
2761 SMLoc Loc = Parser.getTok().getLoc();
2762 if (getParser().ParseExpression(ShiftAmount)) {
2763 Error(Loc, "illegal expression");
2764 return MatchOperand_ParseFail;
2765 }
2766 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2767 if (!CE) {
2768 Error(Loc, "constant expression expected");
2769 return MatchOperand_ParseFail;
2770 }
2771 int Val = CE->getValue();
2772 if (Val < Low || Val > High) {
2773 Error(Loc, "immediate value out of range");
2774 return MatchOperand_ParseFail;
2775 }
2776
2777 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
2778
2779 return MatchOperand_Success;
2780}
2781
Jim Grosbach0a547702011-07-22 17:44:50 +00002782ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2783parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2784 const AsmToken &Tok = Parser.getTok();
2785 SMLoc S = Tok.getLoc();
2786 if (Tok.isNot(AsmToken::Identifier)) {
2787 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2788 return MatchOperand_ParseFail;
2789 }
2790 int Val = StringSwitch<int>(Tok.getString())
2791 .Case("be", 1)
2792 .Case("le", 0)
2793 .Default(-1);
2794 Parser.Lex(); // Eat the token.
2795
2796 if (Val == -1) {
2797 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2798 return MatchOperand_ParseFail;
2799 }
2800 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
2801 getContext()),
2802 S, Parser.getTok().getLoc()));
2803 return MatchOperand_Success;
2804}
2805
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002806/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
2807/// instructions. Legal values are:
2808/// lsl #n 'n' in [0,31]
2809/// asr #n 'n' in [1,32]
2810/// n == 32 encoded as n == 0.
2811ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2812parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2813 const AsmToken &Tok = Parser.getTok();
2814 SMLoc S = Tok.getLoc();
2815 if (Tok.isNot(AsmToken::Identifier)) {
2816 Error(S, "shift operator 'asr' or 'lsl' expected");
2817 return MatchOperand_ParseFail;
2818 }
2819 StringRef ShiftName = Tok.getString();
2820 bool isASR;
2821 if (ShiftName == "lsl" || ShiftName == "LSL")
2822 isASR = false;
2823 else if (ShiftName == "asr" || ShiftName == "ASR")
2824 isASR = true;
2825 else {
2826 Error(S, "shift operator 'asr' or 'lsl' expected");
2827 return MatchOperand_ParseFail;
2828 }
2829 Parser.Lex(); // Eat the operator.
2830
2831 // A '#' and a shift amount.
2832 if (Parser.getTok().isNot(AsmToken::Hash)) {
2833 Error(Parser.getTok().getLoc(), "'#' expected");
2834 return MatchOperand_ParseFail;
2835 }
2836 Parser.Lex(); // Eat hash token.
2837
2838 const MCExpr *ShiftAmount;
2839 SMLoc E = Parser.getTok().getLoc();
2840 if (getParser().ParseExpression(ShiftAmount)) {
2841 Error(E, "malformed shift expression");
2842 return MatchOperand_ParseFail;
2843 }
2844 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2845 if (!CE) {
2846 Error(E, "shift amount must be an immediate");
2847 return MatchOperand_ParseFail;
2848 }
2849
2850 int64_t Val = CE->getValue();
2851 if (isASR) {
2852 // Shift amount must be in [1,32]
2853 if (Val < 1 || Val > 32) {
2854 Error(E, "'asr' shift amount must be in range [1,32]");
2855 return MatchOperand_ParseFail;
2856 }
Owen Andersonf01e2de2011-09-26 21:06:22 +00002857 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
2858 if (isThumb() && Val == 32) {
2859 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
2860 return MatchOperand_ParseFail;
2861 }
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002862 if (Val == 32) Val = 0;
2863 } else {
2864 // Shift amount must be in [1,32]
2865 if (Val < 0 || Val > 31) {
2866 Error(E, "'lsr' shift amount must be in range [0,31]");
2867 return MatchOperand_ParseFail;
2868 }
2869 }
2870
2871 E = Parser.getTok().getLoc();
2872 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
2873
2874 return MatchOperand_Success;
2875}
2876
Jim Grosbach833b9d32011-07-27 20:15:40 +00002877/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
2878/// of instructions. Legal values are:
2879/// ror #n 'n' in {0, 8, 16, 24}
2880ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2881parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2882 const AsmToken &Tok = Parser.getTok();
2883 SMLoc S = Tok.getLoc();
Jim Grosbach82213192011-09-19 20:29:33 +00002884 if (Tok.isNot(AsmToken::Identifier))
2885 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00002886 StringRef ShiftName = Tok.getString();
Jim Grosbach82213192011-09-19 20:29:33 +00002887 if (ShiftName != "ror" && ShiftName != "ROR")
2888 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00002889 Parser.Lex(); // Eat the operator.
2890
2891 // A '#' and a rotate amount.
2892 if (Parser.getTok().isNot(AsmToken::Hash)) {
2893 Error(Parser.getTok().getLoc(), "'#' expected");
2894 return MatchOperand_ParseFail;
2895 }
2896 Parser.Lex(); // Eat hash token.
2897
2898 const MCExpr *ShiftAmount;
2899 SMLoc E = Parser.getTok().getLoc();
2900 if (getParser().ParseExpression(ShiftAmount)) {
2901 Error(E, "malformed rotate expression");
2902 return MatchOperand_ParseFail;
2903 }
2904 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2905 if (!CE) {
2906 Error(E, "rotate amount must be an immediate");
2907 return MatchOperand_ParseFail;
2908 }
2909
2910 int64_t Val = CE->getValue();
2911 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
2912 // normally, zero is represented in asm by omitting the rotate operand
2913 // entirely.
2914 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
2915 Error(E, "'ror' rotate amount must be 8, 16, or 24");
2916 return MatchOperand_ParseFail;
2917 }
2918
2919 E = Parser.getTok().getLoc();
2920 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
2921
2922 return MatchOperand_Success;
2923}
2924
Jim Grosbach864b6092011-07-28 21:34:26 +00002925ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2926parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2927 SMLoc S = Parser.getTok().getLoc();
2928 // The bitfield descriptor is really two operands, the LSB and the width.
2929 if (Parser.getTok().isNot(AsmToken::Hash)) {
2930 Error(Parser.getTok().getLoc(), "'#' expected");
2931 return MatchOperand_ParseFail;
2932 }
2933 Parser.Lex(); // Eat hash token.
2934
2935 const MCExpr *LSBExpr;
2936 SMLoc E = Parser.getTok().getLoc();
2937 if (getParser().ParseExpression(LSBExpr)) {
2938 Error(E, "malformed immediate expression");
2939 return MatchOperand_ParseFail;
2940 }
2941 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
2942 if (!CE) {
2943 Error(E, "'lsb' operand must be an immediate");
2944 return MatchOperand_ParseFail;
2945 }
2946
2947 int64_t LSB = CE->getValue();
2948 // The LSB must be in the range [0,31]
2949 if (LSB < 0 || LSB > 31) {
2950 Error(E, "'lsb' operand must be in the range [0,31]");
2951 return MatchOperand_ParseFail;
2952 }
2953 E = Parser.getTok().getLoc();
2954
2955 // Expect another immediate operand.
2956 if (Parser.getTok().isNot(AsmToken::Comma)) {
2957 Error(Parser.getTok().getLoc(), "too few operands");
2958 return MatchOperand_ParseFail;
2959 }
2960 Parser.Lex(); // Eat hash token.
2961 if (Parser.getTok().isNot(AsmToken::Hash)) {
2962 Error(Parser.getTok().getLoc(), "'#' expected");
2963 return MatchOperand_ParseFail;
2964 }
2965 Parser.Lex(); // Eat hash token.
2966
2967 const MCExpr *WidthExpr;
2968 if (getParser().ParseExpression(WidthExpr)) {
2969 Error(E, "malformed immediate expression");
2970 return MatchOperand_ParseFail;
2971 }
2972 CE = dyn_cast<MCConstantExpr>(WidthExpr);
2973 if (!CE) {
2974 Error(E, "'width' operand must be an immediate");
2975 return MatchOperand_ParseFail;
2976 }
2977
2978 int64_t Width = CE->getValue();
2979 // The LSB must be in the range [1,32-lsb]
2980 if (Width < 1 || Width > 32 - LSB) {
2981 Error(E, "'width' operand must be in the range [1,32-lsb]");
2982 return MatchOperand_ParseFail;
2983 }
2984 E = Parser.getTok().getLoc();
2985
2986 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
2987
2988 return MatchOperand_Success;
2989}
2990
Jim Grosbachd3595712011-08-03 23:50:40 +00002991ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2992parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2993 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachc320c852011-08-05 21:28:30 +00002994 // postidx_reg := '+' register {, shift}
2995 // | '-' register {, shift}
2996 // | register {, shift}
Jim Grosbachd3595712011-08-03 23:50:40 +00002997
2998 // This method must return MatchOperand_NoMatch without consuming any tokens
2999 // in the case where there is no match, as other alternatives take other
3000 // parse methods.
3001 AsmToken Tok = Parser.getTok();
3002 SMLoc S = Tok.getLoc();
3003 bool haveEaten = false;
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00003004 bool isAdd = true;
Jim Grosbachd3595712011-08-03 23:50:40 +00003005 int Reg = -1;
3006 if (Tok.is(AsmToken::Plus)) {
3007 Parser.Lex(); // Eat the '+' token.
3008 haveEaten = true;
3009 } else if (Tok.is(AsmToken::Minus)) {
3010 Parser.Lex(); // Eat the '-' token.
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00003011 isAdd = false;
Jim Grosbachd3595712011-08-03 23:50:40 +00003012 haveEaten = true;
3013 }
3014 if (Parser.getTok().is(AsmToken::Identifier))
3015 Reg = tryParseRegister();
3016 if (Reg == -1) {
3017 if (!haveEaten)
3018 return MatchOperand_NoMatch;
3019 Error(Parser.getTok().getLoc(), "register expected");
3020 return MatchOperand_ParseFail;
3021 }
3022 SMLoc E = Parser.getTok().getLoc();
3023
Jim Grosbachc320c852011-08-05 21:28:30 +00003024 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3025 unsigned ShiftImm = 0;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00003026 if (Parser.getTok().is(AsmToken::Comma)) {
3027 Parser.Lex(); // Eat the ','.
3028 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3029 return MatchOperand_ParseFail;
3030 }
Jim Grosbachc320c852011-08-05 21:28:30 +00003031
3032 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3033 ShiftImm, S, E));
Jim Grosbachd3595712011-08-03 23:50:40 +00003034
3035 return MatchOperand_Success;
3036}
3037
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00003038ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3039parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3040 // Check for a post-index addressing register operand. Specifically:
3041 // am3offset := '+' register
3042 // | '-' register
3043 // | register
3044 // | # imm
3045 // | # + imm
3046 // | # - imm
3047
3048 // This method must return MatchOperand_NoMatch without consuming any tokens
3049 // in the case where there is no match, as other alternatives take other
3050 // parse methods.
3051 AsmToken Tok = Parser.getTok();
3052 SMLoc S = Tok.getLoc();
3053
3054 // Do immediates first, as we always parse those if we have a '#'.
3055 if (Parser.getTok().is(AsmToken::Hash)) {
3056 Parser.Lex(); // Eat the '#'.
3057 // Explicitly look for a '-', as we need to encode negative zero
3058 // differently.
3059 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3060 const MCExpr *Offset;
3061 if (getParser().ParseExpression(Offset))
3062 return MatchOperand_ParseFail;
3063 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3064 if (!CE) {
3065 Error(S, "constant expression expected");
3066 return MatchOperand_ParseFail;
3067 }
3068 SMLoc E = Tok.getLoc();
3069 // Negative zero is encoded as the flag value INT32_MIN.
3070 int32_t Val = CE->getValue();
3071 if (isNegative && Val == 0)
3072 Val = INT32_MIN;
3073
3074 Operands.push_back(
3075 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3076
3077 return MatchOperand_Success;
3078 }
3079
3080
3081 bool haveEaten = false;
3082 bool isAdd = true;
3083 int Reg = -1;
3084 if (Tok.is(AsmToken::Plus)) {
3085 Parser.Lex(); // Eat the '+' token.
3086 haveEaten = true;
3087 } else if (Tok.is(AsmToken::Minus)) {
3088 Parser.Lex(); // Eat the '-' token.
3089 isAdd = false;
3090 haveEaten = true;
3091 }
3092 if (Parser.getTok().is(AsmToken::Identifier))
3093 Reg = tryParseRegister();
3094 if (Reg == -1) {
3095 if (!haveEaten)
3096 return MatchOperand_NoMatch;
3097 Error(Parser.getTok().getLoc(), "register expected");
3098 return MatchOperand_ParseFail;
3099 }
3100 SMLoc E = Parser.getTok().getLoc();
3101
3102 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3103 0, S, E));
3104
3105 return MatchOperand_Success;
3106}
3107
Jim Grosbach7db8d692011-09-08 22:07:06 +00003108/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3109/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3110/// when they refer multiple MIOperands inside a single one.
3111bool ARMAsmParser::
3112cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3113 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3114 // Rt, Rt2
3115 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3116 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3117 // Create a writeback register dummy placeholder.
3118 Inst.addOperand(MCOperand::CreateReg(0));
3119 // addr
3120 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3121 // pred
3122 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3123 return true;
3124}
3125
3126/// cvtT2StrdPre - Convert parsed operands to MCInst.
3127/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3128/// when they refer multiple MIOperands inside a single one.
3129bool ARMAsmParser::
3130cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3131 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3132 // Create a writeback register dummy placeholder.
3133 Inst.addOperand(MCOperand::CreateReg(0));
3134 // Rt, Rt2
3135 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3136 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3137 // addr
3138 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3139 // pred
3140 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3141 return true;
3142}
3143
Jim Grosbachc086f682011-09-08 00:39:19 +00003144/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3145/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3146/// when they refer multiple MIOperands inside a single one.
3147bool ARMAsmParser::
3148cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3149 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3150 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3151
3152 // Create a writeback register dummy placeholder.
3153 Inst.addOperand(MCOperand::CreateImm(0));
3154
3155 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3156 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3157 return true;
3158}
3159
Jim Grosbach9c0b86a2011-09-16 21:55:56 +00003160/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3161/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3162/// when they refer multiple MIOperands inside a single one.
3163bool ARMAsmParser::
3164cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3165 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3166 // Create a writeback register dummy placeholder.
3167 Inst.addOperand(MCOperand::CreateImm(0));
3168 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3169 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3170 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3171 return true;
3172}
3173
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003174/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003175/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3176/// when they refer multiple MIOperands inside a single one.
3177bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003178cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003179 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3180 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3181
3182 // Create a writeback register dummy placeholder.
3183 Inst.addOperand(MCOperand::CreateImm(0));
3184
Jim Grosbachd3595712011-08-03 23:50:40 +00003185 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003186 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3187 return true;
3188}
3189
Owen Anderson16d33f32011-08-26 20:43:14 +00003190/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3191/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3192/// when they refer multiple MIOperands inside a single one.
3193bool ARMAsmParser::
3194cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3195 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3196 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3197
3198 // Create a writeback register dummy placeholder.
3199 Inst.addOperand(MCOperand::CreateImm(0));
3200
3201 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3202 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3203 return true;
3204}
3205
3206
Jim Grosbachd564bf32011-08-11 19:22:40 +00003207/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3208/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3209/// when they refer multiple MIOperands inside a single one.
3210bool ARMAsmParser::
3211cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3212 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3213 // Create a writeback register dummy placeholder.
3214 Inst.addOperand(MCOperand::CreateImm(0));
3215 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3216 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3217 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3218 return true;
3219}
3220
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003221/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003222/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3223/// when they refer multiple MIOperands inside a single one.
3224bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003225cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003226 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3227 // Create a writeback register dummy placeholder.
3228 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd564bf32011-08-11 19:22:40 +00003229 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3230 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3231 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbachd3595712011-08-03 23:50:40 +00003232 return true;
3233}
3234
Jim Grosbachd886f8c2011-08-11 21:17:22 +00003235/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3236/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3237/// when they refer multiple MIOperands inside a single one.
3238bool ARMAsmParser::
3239cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3240 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3241 // Create a writeback register dummy placeholder.
3242 Inst.addOperand(MCOperand::CreateImm(0));
3243 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3244 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3245 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3246 return true;
3247}
3248
Jim Grosbachd3595712011-08-03 23:50:40 +00003249/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3250/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3251/// when they refer multiple MIOperands inside a single one.
3252bool ARMAsmParser::
3253cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3254 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3255 // Rt
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003256 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbachd3595712011-08-03 23:50:40 +00003257 // Create a writeback register dummy placeholder.
3258 Inst.addOperand(MCOperand::CreateImm(0));
3259 // addr
3260 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3261 // offset
3262 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3263 // pred
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003264 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3265 return true;
3266}
3267
Jim Grosbachd3595712011-08-03 23:50:40 +00003268/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003269/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3270/// when they refer multiple MIOperands inside a single one.
3271bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003272cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3273 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3274 // Rt
Owen Andersonb0e68992011-07-28 17:18:57 +00003275 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003276 // Create a writeback register dummy placeholder.
3277 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd3595712011-08-03 23:50:40 +00003278 // addr
3279 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3280 // offset
3281 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3282 // pred
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003283 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3284 return true;
3285}
3286
Jim Grosbachd3595712011-08-03 23:50:40 +00003287/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003288/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3289/// when they refer multiple MIOperands inside a single one.
3290bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003291cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3292 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003293 // Create a writeback register dummy placeholder.
3294 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd3595712011-08-03 23:50:40 +00003295 // Rt
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003296 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbachd3595712011-08-03 23:50:40 +00003297 // addr
3298 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3299 // offset
3300 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3301 // pred
3302 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3303 return true;
3304}
3305
3306/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3307/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3308/// when they refer multiple MIOperands inside a single one.
3309bool ARMAsmParser::
3310cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3311 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3312 // Create a writeback register dummy placeholder.
3313 Inst.addOperand(MCOperand::CreateImm(0));
3314 // Rt
3315 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3316 // addr
3317 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3318 // offset
3319 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3320 // pred
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003321 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3322 return true;
3323}
3324
Jim Grosbach5b96b802011-08-10 20:29:19 +00003325/// cvtLdrdPre - Convert parsed operands to MCInst.
3326/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3327/// when they refer multiple MIOperands inside a single one.
3328bool ARMAsmParser::
3329cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3330 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3331 // Rt, Rt2
3332 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3333 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3334 // Create a writeback register dummy placeholder.
3335 Inst.addOperand(MCOperand::CreateImm(0));
3336 // addr
3337 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3338 // pred
3339 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3340 return true;
3341}
3342
Jim Grosbacheb09f492011-08-11 20:28:23 +00003343/// cvtStrdPre - Convert parsed operands to MCInst.
3344/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3345/// when they refer multiple MIOperands inside a single one.
3346bool ARMAsmParser::
3347cvtStrdPre(MCInst &Inst, unsigned Opcode,
3348 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3349 // Create a writeback register dummy placeholder.
3350 Inst.addOperand(MCOperand::CreateImm(0));
3351 // Rt, Rt2
3352 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3353 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3354 // addr
3355 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3356 // pred
3357 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3358 return true;
3359}
3360
Jim Grosbachcd4dd252011-08-10 22:42:16 +00003361/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3362/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3363/// when they refer multiple MIOperands inside a single one.
3364bool ARMAsmParser::
3365cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3366 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3367 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3368 // Create a writeback register dummy placeholder.
3369 Inst.addOperand(MCOperand::CreateImm(0));
3370 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3371 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3372 return true;
3373}
3374
Jim Grosbach8e048492011-08-19 22:07:46 +00003375/// cvtThumbMultiple- Convert parsed operands to MCInst.
3376/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3377/// when they refer multiple MIOperands inside a single one.
3378bool ARMAsmParser::
3379cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3380 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3381 // The second source operand must be the same register as the destination
3382 // operand.
3383 if (Operands.size() == 6 &&
Jim Grosbach459422d2011-08-19 22:30:46 +00003384 (((ARMOperand*)Operands[3])->getReg() !=
3385 ((ARMOperand*)Operands[5])->getReg()) &&
3386 (((ARMOperand*)Operands[3])->getReg() !=
3387 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach8e048492011-08-19 22:07:46 +00003388 Error(Operands[3]->getStartLoc(),
Jim Grosbach459422d2011-08-19 22:30:46 +00003389 "destination register must match source register");
Jim Grosbach8e048492011-08-19 22:07:46 +00003390 return false;
3391 }
3392 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3393 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
3394 ((ARMOperand*)Operands[4])->addRegOperands(Inst, 1);
Jim Grosbach459422d2011-08-19 22:30:46 +00003395 // If we have a three-operand form, use that, else the second source operand
3396 // is just the destination operand again.
3397 if (Operands.size() == 6)
3398 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3399 else
3400 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach8e048492011-08-19 22:07:46 +00003401 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3402
3403 return true;
3404}
Jim Grosbachcd4dd252011-08-10 22:42:16 +00003405
Jim Grosbach3ea06572011-10-24 22:16:58 +00003406bool ARMAsmParser::
3407cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3408 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3409 // Vd
3410 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3411 // Create a writeback register dummy placeholder.
3412 Inst.addOperand(MCOperand::CreateImm(0));
3413 // Vn
3414 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3415 // pred
3416 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3417 return true;
3418}
3419
3420bool ARMAsmParser::
3421cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3422 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3423 // Vd
3424 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3425 // Create a writeback register dummy placeholder.
3426 Inst.addOperand(MCOperand::CreateImm(0));
3427 // Vn
3428 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3429 // Vm
3430 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3431 // pred
3432 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3433 return true;
3434}
3435
Jim Grosbach05df4602011-10-31 21:50:31 +00003436bool ARMAsmParser::
3437cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
3438 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3439 // Create a writeback register dummy placeholder.
3440 Inst.addOperand(MCOperand::CreateImm(0));
3441 // Vn
3442 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3443 // Vt
3444 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3445 // pred
3446 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3447 return true;
3448}
3449
3450bool ARMAsmParser::
3451cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
3452 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3453 // Create a writeback register dummy placeholder.
3454 Inst.addOperand(MCOperand::CreateImm(0));
3455 // Vn
3456 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3457 // Vm
3458 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3459 // Vt
3460 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3461 // pred
3462 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3463 return true;
3464}
3465
Bill Wendlinge18980a2010-11-06 22:36:58 +00003466/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003467/// or an error. The first token must be a '[' when called.
Bill Wendling2063b842010-11-18 23:43:05 +00003468bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003469parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003470 SMLoc S, E;
Sean Callanan936b0d32010-01-19 21:44:56 +00003471 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00003472 "Token is not a Left Bracket");
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003473 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00003474 Parser.Lex(); // Eat left bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003475
Sean Callanan936b0d32010-01-19 21:44:56 +00003476 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003477 int BaseRegNum = tryParseRegister();
Jim Grosbachd3595712011-08-03 23:50:40 +00003478 if (BaseRegNum == -1)
3479 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003480
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00003481 // The next token must either be a comma or a closing bracket.
3482 const AsmToken &Tok = Parser.getTok();
3483 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbachd3595712011-08-03 23:50:40 +00003484 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00003485
Jim Grosbachd3595712011-08-03 23:50:40 +00003486 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003487 E = Tok.getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00003488 Parser.Lex(); // Eat right bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003489
Jim Grosbachd3595712011-08-03 23:50:40 +00003490 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbacha95ec992011-10-11 17:29:55 +00003491 0, 0, false, S, E));
Jim Grosbach32ff5582010-11-29 23:18:01 +00003492
Jim Grosbach40700e02011-09-19 18:42:21 +00003493 // If there's a pre-indexing writeback marker, '!', just add it as a token
3494 // operand. It's rather odd, but syntactically valid.
3495 if (Parser.getTok().is(AsmToken::Exclaim)) {
3496 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3497 Parser.Lex(); // Eat the '!'.
3498 }
3499
Jim Grosbachd3595712011-08-03 23:50:40 +00003500 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003501 }
Daniel Dunbarf5164f42011-01-18 05:34:24 +00003502
Jim Grosbachd3595712011-08-03 23:50:40 +00003503 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3504 Parser.Lex(); // Eat the comma.
Daniel Dunbarf5164f42011-01-18 05:34:24 +00003505
Jim Grosbacha95ec992011-10-11 17:29:55 +00003506 // If we have a ':', it's an alignment specifier.
3507 if (Parser.getTok().is(AsmToken::Colon)) {
3508 Parser.Lex(); // Eat the ':'.
3509 E = Parser.getTok().getLoc();
3510
3511 const MCExpr *Expr;
3512 if (getParser().ParseExpression(Expr))
3513 return true;
3514
3515 // The expression has to be a constant. Memory references with relocations
3516 // don't come through here, as they use the <label> forms of the relevant
3517 // instructions.
3518 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3519 if (!CE)
3520 return Error (E, "constant expression expected");
3521
3522 unsigned Align = 0;
3523 switch (CE->getValue()) {
3524 default:
3525 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3526 case 64: Align = 8; break;
3527 case 128: Align = 16; break;
3528 case 256: Align = 32; break;
3529 }
3530
3531 // Now we should have the closing ']'
3532 E = Parser.getTok().getLoc();
3533 if (Parser.getTok().isNot(AsmToken::RBrac))
3534 return Error(E, "']' expected");
3535 Parser.Lex(); // Eat right bracket token.
3536
3537 // Don't worry about range checking the value here. That's handled by
3538 // the is*() predicates.
3539 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3540 ARM_AM::no_shift, 0, Align,
3541 false, S, E));
3542
3543 // If there's a pre-indexing writeback marker, '!', just add it as a token
3544 // operand.
3545 if (Parser.getTok().is(AsmToken::Exclaim)) {
3546 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3547 Parser.Lex(); // Eat the '!'.
3548 }
3549
3550 return false;
3551 }
3552
3553 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbachd3595712011-08-03 23:50:40 +00003554 // offset.
3555 if (Parser.getTok().is(AsmToken::Hash)) {
3556 Parser.Lex(); // Eat the '#'.
3557 E = Parser.getTok().getLoc();
Daniel Dunbarf5164f42011-01-18 05:34:24 +00003558
Owen Anderson967674d2011-08-29 19:36:44 +00003559 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbachd3595712011-08-03 23:50:40 +00003560 const MCExpr *Offset;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003561 if (getParser().ParseExpression(Offset))
3562 return true;
Jim Grosbachd3595712011-08-03 23:50:40 +00003563
3564 // The expression has to be a constant. Memory references with relocations
3565 // don't come through here, as they use the <label> forms of the relevant
3566 // instructions.
3567 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3568 if (!CE)
3569 return Error (E, "constant expression expected");
3570
Owen Anderson967674d2011-08-29 19:36:44 +00003571 // If the constant was #-0, represent it as INT32_MIN.
3572 int32_t Val = CE->getValue();
3573 if (isNegative && Val == 0)
3574 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3575
Jim Grosbachd3595712011-08-03 23:50:40 +00003576 // Now we should have the closing ']'
3577 E = Parser.getTok().getLoc();
3578 if (Parser.getTok().isNot(AsmToken::RBrac))
3579 return Error(E, "']' expected");
3580 Parser.Lex(); // Eat right bracket token.
3581
3582 // Don't worry about range checking the value here. That's handled by
3583 // the is*() predicates.
3584 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbacha95ec992011-10-11 17:29:55 +00003585 ARM_AM::no_shift, 0, 0,
3586 false, S, E));
Jim Grosbachd3595712011-08-03 23:50:40 +00003587
3588 // If there's a pre-indexing writeback marker, '!', just add it as a token
3589 // operand.
3590 if (Parser.getTok().is(AsmToken::Exclaim)) {
3591 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3592 Parser.Lex(); // Eat the '!'.
3593 }
3594
3595 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003596 }
Jim Grosbachd3595712011-08-03 23:50:40 +00003597
3598 // The register offset is optionally preceded by a '+' or '-'
3599 bool isNegative = false;
3600 if (Parser.getTok().is(AsmToken::Minus)) {
3601 isNegative = true;
3602 Parser.Lex(); // Eat the '-'.
3603 } else if (Parser.getTok().is(AsmToken::Plus)) {
3604 // Nothing to do.
3605 Parser.Lex(); // Eat the '+'.
3606 }
3607
3608 E = Parser.getTok().getLoc();
3609 int OffsetRegNum = tryParseRegister();
3610 if (OffsetRegNum == -1)
3611 return Error(E, "register expected");
3612
3613 // If there's a shift operator, handle it.
3614 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00003615 unsigned ShiftImm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00003616 if (Parser.getTok().is(AsmToken::Comma)) {
3617 Parser.Lex(); // Eat the ','.
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00003618 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbachd3595712011-08-03 23:50:40 +00003619 return true;
3620 }
3621
3622 // Now we should have the closing ']'
3623 E = Parser.getTok().getLoc();
3624 if (Parser.getTok().isNot(AsmToken::RBrac))
3625 return Error(E, "']' expected");
3626 Parser.Lex(); // Eat right bracket token.
3627
3628 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbacha95ec992011-10-11 17:29:55 +00003629 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbachd3595712011-08-03 23:50:40 +00003630 S, E));
3631
Jim Grosbachc320c852011-08-05 21:28:30 +00003632 // If there's a pre-indexing writeback marker, '!', just add it as a token
3633 // operand.
3634 if (Parser.getTok().is(AsmToken::Exclaim)) {
3635 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3636 Parser.Lex(); // Eat the '!'.
3637 }
Jim Grosbachd3595712011-08-03 23:50:40 +00003638
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003639 return false;
3640}
3641
Jim Grosbachd3595712011-08-03 23:50:40 +00003642/// parseMemRegOffsetShift - one of these two:
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003643/// ( lsl | lsr | asr | ror ) , # shift_amount
3644/// rrx
Jim Grosbachd3595712011-08-03 23:50:40 +00003645/// return true if it parses a shift otherwise it returns false.
3646bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
3647 unsigned &Amount) {
3648 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan936b0d32010-01-19 21:44:56 +00003649 const AsmToken &Tok = Parser.getTok();
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003650 if (Tok.isNot(AsmToken::Identifier))
3651 return true;
Benjamin Kramer92d89982010-07-14 22:38:02 +00003652 StringRef ShiftName = Tok.getString();
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003653 if (ShiftName == "lsl" || ShiftName == "LSL")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003654 St = ARM_AM::lsl;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003655 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003656 St = ARM_AM::lsr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003657 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003658 St = ARM_AM::asr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003659 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003660 St = ARM_AM::ror;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003661 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003662 St = ARM_AM::rrx;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003663 else
Jim Grosbachd3595712011-08-03 23:50:40 +00003664 return Error(Loc, "illegal shift operator");
Sean Callanana83fd7d2010-01-19 20:27:46 +00003665 Parser.Lex(); // Eat shift type token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003666
Jim Grosbachd3595712011-08-03 23:50:40 +00003667 // rrx stands alone.
3668 Amount = 0;
3669 if (St != ARM_AM::rrx) {
3670 Loc = Parser.getTok().getLoc();
3671 // A '#' and a shift amount.
3672 const AsmToken &HashTok = Parser.getTok();
3673 if (HashTok.isNot(AsmToken::Hash))
3674 return Error(HashTok.getLoc(), "'#' expected");
3675 Parser.Lex(); // Eat hash token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003676
Jim Grosbachd3595712011-08-03 23:50:40 +00003677 const MCExpr *Expr;
3678 if (getParser().ParseExpression(Expr))
3679 return true;
3680 // Range check the immediate.
3681 // lsl, ror: 0 <= imm <= 31
3682 // lsr, asr: 0 <= imm <= 32
3683 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3684 if (!CE)
3685 return Error(Loc, "shift amount must be an immediate");
3686 int64_t Imm = CE->getValue();
3687 if (Imm < 0 ||
3688 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
3689 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
3690 return Error(Loc, "immediate shift value out of range");
3691 Amount = Imm;
3692 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003693
3694 return false;
3695}
3696
Jim Grosbache7fbce72011-10-03 23:38:36 +00003697/// parseFPImm - A floating point immediate expression operand.
3698ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3699parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3700 SMLoc S = Parser.getTok().getLoc();
3701
3702 if (Parser.getTok().isNot(AsmToken::Hash))
3703 return MatchOperand_NoMatch;
Jim Grosbach741cd732011-10-17 22:26:03 +00003704
3705 // Disambiguate the VMOV forms that can accept an FP immediate.
3706 // vmov.f32 <sreg>, #imm
3707 // vmov.f64 <dreg>, #imm
3708 // vmov.f32 <dreg>, #imm @ vector f32x2
3709 // vmov.f32 <qreg>, #imm @ vector f32x4
3710 //
3711 // There are also the NEON VMOV instructions which expect an
3712 // integer constant. Make sure we don't try to parse an FPImm
3713 // for these:
3714 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
3715 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
3716 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
3717 TyOp->getToken() != ".f64"))
3718 return MatchOperand_NoMatch;
3719
Jim Grosbache7fbce72011-10-03 23:38:36 +00003720 Parser.Lex(); // Eat the '#'.
3721
3722 // Handle negation, as that still comes through as a separate token.
3723 bool isNegative = false;
3724 if (Parser.getTok().is(AsmToken::Minus)) {
3725 isNegative = true;
3726 Parser.Lex();
3727 }
3728 const AsmToken &Tok = Parser.getTok();
3729 if (Tok.is(AsmToken::Real)) {
3730 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
3731 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3732 // If we had a '-' in front, toggle the sign bit.
3733 IntVal ^= (uint64_t)isNegative << 63;
3734 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
3735 Parser.Lex(); // Eat the token.
3736 if (Val == -1) {
3737 TokError("floating point value out of range");
3738 return MatchOperand_ParseFail;
3739 }
3740 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3741 return MatchOperand_Success;
3742 }
3743 if (Tok.is(AsmToken::Integer)) {
3744 int64_t Val = Tok.getIntVal();
3745 Parser.Lex(); // Eat the token.
3746 if (Val > 255 || Val < 0) {
3747 TokError("encoded floating point value out of range");
3748 return MatchOperand_ParseFail;
3749 }
3750 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3751 return MatchOperand_Success;
3752 }
3753
3754 TokError("invalid floating point immediate");
3755 return MatchOperand_ParseFail;
3756}
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003757/// Parse a arm instruction operand. For now this parses the operand regardless
3758/// of the mnemonic.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003759bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003760 StringRef Mnemonic) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003761 SMLoc S, E;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003762
3763 // Check if the current operand has a custom associated parser, if so, try to
3764 // custom parse the operand, or fallback to the general approach.
Jim Grosbach861e49c2011-02-12 01:34:40 +00003765 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3766 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003767 return false;
Jim Grosbach861e49c2011-02-12 01:34:40 +00003768 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3769 // there was a match, but an error occurred, in which case, just return that
3770 // the operand parsing failed.
3771 if (ResTy == MatchOperand_ParseFail)
3772 return true;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003773
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003774 switch (getLexer().getKind()) {
Bill Wendlingee7f1f92010-11-06 21:42:12 +00003775 default:
3776 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling2063b842010-11-18 23:43:05 +00003777 return true;
Jim Grosbachbb24c592011-07-13 18:49:30 +00003778 case AsmToken::Identifier: {
Jim Grosbach4ab23b52011-10-03 21:12:43 +00003779 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003780 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling2063b842010-11-18 23:43:05 +00003781 return false;
Jim Grosbach0d6022d2011-07-26 20:41:24 +00003782 int Res = tryParseShiftRegister(Operands);
Jim Grosbachbb24c592011-07-13 18:49:30 +00003783 if (Res == 0) // success
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003784 return false;
Jim Grosbachbb24c592011-07-13 18:49:30 +00003785 else if (Res == -1) // irrecoverable error
3786 return true;
Jim Grosbach4ab23b52011-10-03 21:12:43 +00003787 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
3788 S = Parser.getTok().getLoc();
3789 Parser.Lex();
3790 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
3791 return false;
3792 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00003793
3794 // Fall though for the Identifier case that is not a register or a
3795 // special name.
Jim Grosbachbb24c592011-07-13 18:49:30 +00003796 }
Jim Grosbach4e380352011-10-26 21:14:08 +00003797 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderbyb084be92011-01-13 20:32:36 +00003798 case AsmToken::Integer: // things like 1f and 2b as a branch targets
3799 case AsmToken::Dot: { // . as a branch target
Kevin Enderby146dcf22009-10-15 20:48:48 +00003800 // This was not a register so parse other operands that start with an
3801 // identifier (like labels) as expressions and create them as immediates.
3802 const MCExpr *IdVal;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003803 S = Parser.getTok().getLoc();
Kevin Enderby146dcf22009-10-15 20:48:48 +00003804 if (getParser().ParseExpression(IdVal))
Bill Wendling2063b842010-11-18 23:43:05 +00003805 return true;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003806 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling2063b842010-11-18 23:43:05 +00003807 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
3808 return false;
3809 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003810 case AsmToken::LBrac:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003811 return parseMemory(Operands);
Kevin Enderbya2b99102009-10-09 21:12:28 +00003812 case AsmToken::LCurly:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003813 return parseRegisterList(Operands);
Owen Andersonf02d98d2011-08-29 17:17:09 +00003814 case AsmToken::Hash: {
Kevin Enderby3a80dac2009-10-13 23:33:38 +00003815 // #42 -> immediate.
3816 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003817 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00003818 Parser.Lex();
Owen Andersonf02d98d2011-08-29 17:17:09 +00003819 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby146dcf22009-10-15 20:48:48 +00003820 const MCExpr *ImmVal;
3821 if (getParser().ParseExpression(ImmVal))
Bill Wendling2063b842010-11-18 23:43:05 +00003822 return true;
Owen Andersonf02d98d2011-08-29 17:17:09 +00003823 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
3824 if (!CE) {
3825 Error(S, "constant expression expected");
3826 return MatchOperand_ParseFail;
3827 }
3828 int32_t Val = CE->getValue();
3829 if (isNegative && Val == 0)
3830 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003831 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling2063b842010-11-18 23:43:05 +00003832 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
3833 return false;
Owen Andersonf02d98d2011-08-29 17:17:09 +00003834 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00003835 case AsmToken::Colon: {
3836 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng965b3c72011-01-13 07:58:56 +00003837 // FIXME: Check it's an expression prefix,
3838 // e.g. (FOO - :lower16:BAR) isn't legal.
3839 ARMMCExpr::VariantKind RefKind;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003840 if (parsePrefix(RefKind))
Jason W Kim1f7bc072011-01-11 23:53:41 +00003841 return true;
3842
Evan Cheng965b3c72011-01-13 07:58:56 +00003843 const MCExpr *SubExprVal;
3844 if (getParser().ParseExpression(SubExprVal))
Jason W Kim1f7bc072011-01-11 23:53:41 +00003845 return true;
3846
Evan Cheng965b3c72011-01-13 07:58:56 +00003847 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
3848 getContext());
Jason W Kim1f7bc072011-01-11 23:53:41 +00003849 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng965b3c72011-01-13 07:58:56 +00003850 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim1f7bc072011-01-11 23:53:41 +00003851 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003852 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00003853 }
3854}
3855
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003856// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng965b3c72011-01-13 07:58:56 +00003857// :lower16: and :upper16:.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003858bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng965b3c72011-01-13 07:58:56 +00003859 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim1f7bc072011-01-11 23:53:41 +00003860
3861 // :lower16: and :upper16: modifiers
Jason W Kim93229972011-01-13 00:27:00 +00003862 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim1f7bc072011-01-11 23:53:41 +00003863 Parser.Lex(); // Eat ':'
3864
3865 if (getLexer().isNot(AsmToken::Identifier)) {
3866 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
3867 return true;
3868 }
3869
3870 StringRef IDVal = Parser.getTok().getIdentifier();
3871 if (IDVal == "lower16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00003872 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00003873 } else if (IDVal == "upper16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00003874 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00003875 } else {
3876 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
3877 return true;
3878 }
3879 Parser.Lex();
3880
3881 if (getLexer().isNot(AsmToken::Colon)) {
3882 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
3883 return true;
3884 }
3885 Parser.Lex(); // Eat the last ':'
3886 return false;
3887}
3888
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003889/// \brief Given a mnemonic, split out possible predication code and carry
3890/// setting letters to form a canonical mnemonic and flags.
3891//
Daniel Dunbar876bb0182011-01-10 12:24:52 +00003892// FIXME: Would be nice to autogen this.
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003893// FIXME: This is a bit of a maze of special cases.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003894StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00003895 unsigned &PredicationCode,
3896 bool &CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003897 unsigned &ProcessorIMod,
3898 StringRef &ITMask) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003899 PredicationCode = ARMCC::AL;
3900 CarrySetting = false;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003901 ProcessorIMod = 0;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003902
Daniel Dunbar876bb0182011-01-10 12:24:52 +00003903 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003904 //
3905 // FIXME: Would be nice to autogen this.
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00003906 if ((Mnemonic == "movs" && isThumb()) ||
3907 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
3908 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
3909 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
3910 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
3911 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
3912 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
3913 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003914 return Mnemonic;
Daniel Dunbar75d26be2010-08-11 06:37:16 +00003915
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00003916 // First, split out any predication code. Ignore mnemonics we know aren't
3917 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbach8d114902011-07-20 18:20:31 +00003918 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach0c398b92011-07-27 21:58:11 +00003919 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach3636be32011-08-22 23:55:58 +00003920 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbachf6d5d602011-09-01 18:22:13 +00003921 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00003922 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
3923 .Case("eq", ARMCC::EQ)
3924 .Case("ne", ARMCC::NE)
3925 .Case("hs", ARMCC::HS)
3926 .Case("cs", ARMCC::HS)
3927 .Case("lo", ARMCC::LO)
3928 .Case("cc", ARMCC::LO)
3929 .Case("mi", ARMCC::MI)
3930 .Case("pl", ARMCC::PL)
3931 .Case("vs", ARMCC::VS)
3932 .Case("vc", ARMCC::VC)
3933 .Case("hi", ARMCC::HI)
3934 .Case("ls", ARMCC::LS)
3935 .Case("ge", ARMCC::GE)
3936 .Case("lt", ARMCC::LT)
3937 .Case("gt", ARMCC::GT)
3938 .Case("le", ARMCC::LE)
3939 .Case("al", ARMCC::AL)
3940 .Default(~0U);
3941 if (CC != ~0U) {
3942 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
3943 PredicationCode = CC;
3944 }
Bill Wendling193961b2010-10-29 23:50:21 +00003945 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00003946
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003947 // Next, determine if we have a carry setting bit. We explicitly ignore all
3948 // the instructions we know end in 's'.
3949 if (Mnemonic.endswith("s") &&
Jim Grosbachd3e8e292011-08-17 22:49:09 +00003950 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00003951 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
3952 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
3953 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach51726e22011-07-29 20:26:09 +00003954 Mnemonic == "vrsqrts" || Mnemonic == "srs" ||
3955 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003956 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
3957 CarrySetting = true;
3958 }
3959
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003960 // The "cps" instruction can have a interrupt mode operand which is glued into
3961 // the mnemonic. Check if this is the case, split it and parse the imod op
3962 if (Mnemonic.startswith("cps")) {
3963 // Split out any imod code.
3964 unsigned IMod =
3965 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
3966 .Case("ie", ARM_PROC::IE)
3967 .Case("id", ARM_PROC::ID)
3968 .Default(~0U);
3969 if (IMod != ~0U) {
3970 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
3971 ProcessorIMod = IMod;
3972 }
3973 }
3974
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003975 // The "it" instruction has the condition mask on the end of the mnemonic.
3976 if (Mnemonic.startswith("it")) {
3977 ITMask = Mnemonic.slice(2, Mnemonic.size());
3978 Mnemonic = Mnemonic.slice(0, 2);
3979 }
3980
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003981 return Mnemonic;
3982}
Daniel Dunbar5a384c82011-01-11 15:59:53 +00003983
3984/// \brief Given a canonical mnemonic, determine if the instruction ever allows
3985/// inclusion of carry set or predication code operands.
3986//
3987// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00003988void ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003989getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00003990 bool &CanAcceptPredicationCode) {
Daniel Dunbar09264122011-01-11 19:06:29 +00003991 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
3992 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00003993 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00003994 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00003995 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00003996 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00003997 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00003998 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00003999 Mnemonic == "mla" || Mnemonic == "smlal" ||
4000 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbar09264122011-01-11 19:06:29 +00004001 CanAcceptCarrySet = true;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004002 } else
Daniel Dunbar09264122011-01-11 19:06:29 +00004003 CanAcceptCarrySet = false;
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004004
Daniel Dunbar09264122011-01-11 19:06:29 +00004005 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4006 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4007 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4008 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbach803898f2011-09-06 20:27:04 +00004009 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4010 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach25977222011-08-19 23:24:36 +00004011 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach93981412011-10-11 21:55:36 +00004012 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4013 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4014 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbachb9d4e372011-08-26 22:21:51 +00004015 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4016 !isThumb()) ||
Jim Grosbachb908b7a2011-09-10 00:15:36 +00004017 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004018 CanAcceptPredicationCode = false;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004019 } else
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004020 CanAcceptPredicationCode = true;
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004021
Jim Grosbach6c45b752011-09-16 16:39:25 +00004022 if (isThumb()) {
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004023 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbachb98ab912011-06-30 22:10:46 +00004024 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004025 CanAcceptPredicationCode = false;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004026 }
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004027}
4028
Jim Grosbach7283da92011-08-16 21:12:37 +00004029bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4030 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004031 // FIXME: This is all horribly hacky. We really need a better way to deal
4032 // with optional operands like this in the matcher table.
Jim Grosbach7283da92011-08-16 21:12:37 +00004033
4034 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4035 // another does not. Specifically, the MOVW instruction does not. So we
4036 // special case it here and remove the defaulted (non-setting) cc_out
4037 // operand if that's the instruction we're trying to match.
4038 //
4039 // We do this as post-processing of the explicit operands rather than just
4040 // conditionally adding the cc_out in the first place because we need
4041 // to check the type of the parsed immediate operand.
Owen Andersond7791b92011-09-14 22:46:14 +00004042 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbach7283da92011-08-16 21:12:37 +00004043 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4044 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4045 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4046 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00004047
4048 // Register-register 'add' for thumb does not have a cc_out operand
4049 // when there are only two register operands.
4050 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4051 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4052 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4053 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4054 return true;
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004055 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004056 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4057 // have to check the immediate range here since Thumb2 has a variant
4058 // that can handle a different range and has a cc_out operand.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004059 if (((isThumb() && Mnemonic == "add") ||
4060 (isThumbTwo() && Mnemonic == "sub")) &&
4061 Operands.size() == 6 &&
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004062 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4063 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4064 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004065 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4066 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4067 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004068 return true;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004069 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4070 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004071 // selecting via the generic "add" mnemonic, so to know that we
4072 // should remove the cc_out operand, we have to explicitly check that
4073 // it's not one of the other variants. Ugh.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004074 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4075 Operands.size() == 6 &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004076 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4077 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4078 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4079 // Nest conditions rather than one big 'if' statement for readability.
4080 //
4081 // If either register is a high reg, it's either one of the SP
4082 // variants (handled above) or a 32-bit encoding, so we just
4083 // check against T3.
4084 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4085 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4086 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4087 return false;
4088 // If both registers are low, we're in an IT block, and the immediate is
4089 // in range, we should use encoding T1 instead, which has a cc_out.
4090 if (inITBlock() &&
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004091 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004092 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4093 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4094 return false;
4095
4096 // Otherwise, we use encoding T4, which does not have a cc_out
4097 // operand.
4098 return true;
4099 }
4100
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004101 // The thumb2 multiply instruction doesn't have a CCOut register, so
4102 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4103 // use the 16-bit encoding or not.
4104 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4105 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4106 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4107 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4108 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4109 // If the registers aren't low regs, the destination reg isn't the
4110 // same as one of the source regs, or the cc_out operand is zero
4111 // outside of an IT block, we have to use the 32-bit encoding, so
4112 // remove the cc_out operand.
4113 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4114 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4115 !inITBlock() ||
4116 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4117 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4118 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4119 static_cast<ARMOperand*>(Operands[4])->getReg())))
4120 return true;
4121
4122
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004123
Jim Grosbach4b701af2011-08-24 21:42:27 +00004124 // Register-register 'add/sub' for thumb does not have a cc_out operand
4125 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4126 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4127 // right, this will result in better diagnostics (which operand is off)
4128 // anyway.
4129 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4130 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004131 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4132 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4133 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4134 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00004135
Jim Grosbach7283da92011-08-16 21:12:37 +00004136 return false;
4137}
4138
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004139/// Parse an arm instruction mnemonic followed by its operands.
4140bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4141 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4142 // Create the leading tokens for the mnemonic, split by '.' characters.
4143 size_t Start = 0, Next = Name.find('.');
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004144 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004145
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004146 // Split out the predication code and carry setting flag from the mnemonic.
4147 unsigned PredicationCode;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004148 unsigned ProcessorIMod;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004149 bool CarrySetting;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004150 StringRef ITMask;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004151 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004152 ProcessorIMod, ITMask);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004153
Jim Grosbach1c171b12011-08-25 17:23:55 +00004154 // In Thumb1, only the branch (B) instruction can be predicated.
4155 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4156 Parser.EatToEndOfStatement();
4157 return Error(NameLoc, "conditional execution not supported in Thumb1");
4158 }
4159
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004160 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4161
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004162 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4163 // is the mask as it will be for the IT encoding if the conditional
4164 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4165 // where the conditional bit0 is zero, the instruction post-processing
4166 // will adjust the mask accordingly.
4167 if (Mnemonic == "it") {
Jim Grosbached16ec42011-08-29 22:24:09 +00004168 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4169 if (ITMask.size() > 3) {
4170 Parser.EatToEndOfStatement();
4171 return Error(Loc, "too many conditions on IT instruction");
4172 }
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004173 unsigned Mask = 8;
4174 for (unsigned i = ITMask.size(); i != 0; --i) {
4175 char pos = ITMask[i - 1];
4176 if (pos != 't' && pos != 'e') {
4177 Parser.EatToEndOfStatement();
Jim Grosbached16ec42011-08-29 22:24:09 +00004178 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004179 }
4180 Mask >>= 1;
4181 if (ITMask[i - 1] == 't')
4182 Mask |= 8;
4183 }
Jim Grosbached16ec42011-08-29 22:24:09 +00004184 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004185 }
4186
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004187 // FIXME: This is all a pretty gross hack. We should automatically handle
4188 // optional operands like this via tblgen.
Bill Wendling219dabd2010-11-21 10:56:05 +00004189
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004190 // Next, add the CCOut and ConditionCode operands, if needed.
4191 //
4192 // For mnemonics which can ever incorporate a carry setting bit or predication
4193 // code, our matching model involves us always generating CCOut and
4194 // ConditionCode operands to match the mnemonic "as written" and then we let
4195 // the matcher deal with finding the right instruction or generating an
4196 // appropriate error.
4197 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004198 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004199
Jim Grosbach03a8a162011-07-14 22:04:21 +00004200 // If we had a carry-set on an instruction that can't do that, issue an
4201 // error.
4202 if (!CanAcceptCarrySet && CarrySetting) {
4203 Parser.EatToEndOfStatement();
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004204 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach03a8a162011-07-14 22:04:21 +00004205 "' can not set flags, but 's' suffix specified");
4206 }
Jim Grosbach0a547702011-07-22 17:44:50 +00004207 // If we had a predication code on an instruction that can't do that, issue an
4208 // error.
4209 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4210 Parser.EatToEndOfStatement();
4211 return Error(NameLoc, "instruction '" + Mnemonic +
4212 "' is not predicable, but condition code specified");
4213 }
Jim Grosbach03a8a162011-07-14 22:04:21 +00004214
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004215 // Add the carry setting operand, if necessary.
Jim Grosbached16ec42011-08-29 22:24:09 +00004216 if (CanAcceptCarrySet) {
4217 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004218 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbached16ec42011-08-29 22:24:09 +00004219 Loc));
4220 }
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004221
4222 // Add the predication code operand, if necessary.
4223 if (CanAcceptPredicationCode) {
Jim Grosbached16ec42011-08-29 22:24:09 +00004224 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4225 CarrySetting);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004226 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbached16ec42011-08-29 22:24:09 +00004227 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004228 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004229
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004230 // Add the processor imod operand, if necessary.
4231 if (ProcessorIMod) {
4232 Operands.push_back(ARMOperand::CreateImm(
4233 MCConstantExpr::Create(ProcessorIMod, getContext()),
4234 NameLoc, NameLoc));
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004235 }
4236
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004237 // Add the remaining tokens in the mnemonic.
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004238 while (Next != StringRef::npos) {
4239 Start = Next;
4240 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004241 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004242
Jim Grosbach838ed3a2011-08-24 22:19:48 +00004243 // For now, we're only parsing Thumb1 (for the most part), so
4244 // just ignore ".n" qualifiers. We'll use them to restrict
4245 // matching when we do Thumb2.
Jim Grosbach39c6e1d2011-09-07 16:06:04 +00004246 if (ExtraToken != ".n") {
4247 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4248 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4249 }
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004250 }
4251
4252 // Read the remaining operands.
4253 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004254 // Read the first operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004255 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnera2a9d162010-09-11 16:18:25 +00004256 Parser.EatToEndOfStatement();
4257 return true;
4258 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004259
4260 while (getLexer().is(AsmToken::Comma)) {
Sean Callanana83fd7d2010-01-19 20:27:46 +00004261 Parser.Lex(); // Eat the comma.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004262
4263 // Parse and remember the operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004264 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnera2a9d162010-09-11 16:18:25 +00004265 Parser.EatToEndOfStatement();
4266 return true;
4267 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004268 }
4269 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00004270
Chris Lattnera2a9d162010-09-11 16:18:25 +00004271 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbachb8d9f512011-10-07 18:27:04 +00004272 SMLoc Loc = getLexer().getLoc();
Chris Lattnera2a9d162010-09-11 16:18:25 +00004273 Parser.EatToEndOfStatement();
Jim Grosbachb8d9f512011-10-07 18:27:04 +00004274 return Error(Loc, "unexpected token in argument list");
Chris Lattnera2a9d162010-09-11 16:18:25 +00004275 }
Bill Wendlingee7f1f92010-11-06 21:42:12 +00004276
Chris Lattner91689c12010-09-08 05:10:46 +00004277 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004278
Jim Grosbach7283da92011-08-16 21:12:37 +00004279 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4280 // do and don't have a cc_out optional-def operand. With some spot-checks
4281 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004282 // parse and adjust accordingly before actually matching. We shouldn't ever
4283 // try to remove a cc_out operand that was explicitly set on the the
4284 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4285 // table driven matcher doesn't fit well with the ARM instruction set.
4286 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004287 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4288 Operands.erase(Operands.begin() + 1);
4289 delete Op;
4290 }
4291
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00004292 // ARM mode 'blx' need special handling, as the register operand version
4293 // is predicable, but the label operand version is not. So, we can't rely
4294 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach6e5778f2011-10-07 23:24:09 +00004295 // a k_CondCode operand in the list. If we're trying to match the label
4296 // version, remove the k_CondCode operand here.
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00004297 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4298 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4299 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4300 Operands.erase(Operands.begin() + 1);
4301 delete Op;
4302 }
Jim Grosbach8cffa282011-08-11 23:51:13 +00004303
4304 // The vector-compare-to-zero instructions have a literal token "#0" at
4305 // the end that comes to here as an immediate operand. Convert it to a
4306 // token to play nicely with the matcher.
4307 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4308 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4309 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4310 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4311 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4312 if (CE && CE->getValue() == 0) {
4313 Operands.erase(Operands.begin() + 5);
4314 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4315 delete Op;
4316 }
4317 }
Jim Grosbach46b66462011-10-03 22:30:24 +00004318 // VCMP{E} does the same thing, but with a different operand count.
4319 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4320 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4321 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4322 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4323 if (CE && CE->getValue() == 0) {
4324 Operands.erase(Operands.begin() + 4);
4325 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4326 delete Op;
4327 }
4328 }
Jim Grosbachc3c32d92011-08-22 23:47:13 +00004329 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
4330 // end. Convert it to a token here.
4331 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
4332 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4333 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4334 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4335 if (CE && CE->getValue() == 0) {
4336 Operands.erase(Operands.begin() + 5);
4337 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4338 delete Op;
4339 }
4340 }
4341
Chris Lattnerf29c0b62010-01-14 22:21:20 +00004342 return false;
Kevin Enderbyccab3172009-09-15 00:27:25 +00004343}
4344
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004345// Validate context-sensitive operand constraints.
Jim Grosbach169b2be2011-08-23 18:13:04 +00004346
4347// return 'true' if register list contains non-low GPR registers,
4348// 'false' otherwise. If Reg is in the register list or is HiReg, set
4349// 'containsReg' to true.
4350static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4351 unsigned HiReg, bool &containsReg) {
4352 containsReg = false;
4353 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4354 unsigned OpReg = Inst.getOperand(i).getReg();
4355 if (OpReg == Reg)
4356 containsReg = true;
4357 // Anything other than a low register isn't legal here.
4358 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4359 return true;
4360 }
4361 return false;
4362}
4363
Jim Grosbacha31f2232011-09-07 18:05:34 +00004364// Check if the specified regisgter is in the register list of the inst,
4365// starting at the indicated operand number.
4366static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4367 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4368 unsigned OpReg = Inst.getOperand(i).getReg();
4369 if (OpReg == Reg)
4370 return true;
4371 }
4372 return false;
4373}
4374
Jim Grosbached16ec42011-08-29 22:24:09 +00004375// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4376// the ARMInsts array) instead. Getting that here requires awkward
4377// API changes, though. Better way?
4378namespace llvm {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00004379extern const MCInstrDesc ARMInsts[];
Jim Grosbached16ec42011-08-29 22:24:09 +00004380}
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00004381static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbached16ec42011-08-29 22:24:09 +00004382 return ARMInsts[Opcode];
4383}
4384
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004385// FIXME: We would really like to be able to tablegen'erate this.
4386bool ARMAsmParser::
4387validateInstruction(MCInst &Inst,
4388 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00004389 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbached16ec42011-08-29 22:24:09 +00004390 SMLoc Loc = Operands[0]->getStartLoc();
4391 // Check the IT block state first.
Owen Anderson44ae2da2011-09-13 17:59:19 +00004392 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4393 // being allowed in IT blocks, but not being predicable. It just always
4394 // executes.
4395 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbached16ec42011-08-29 22:24:09 +00004396 unsigned bit = 1;
4397 if (ITState.FirstCond)
4398 ITState.FirstCond = false;
4399 else
Jim Grosbacha0d34d32011-09-02 23:22:08 +00004400 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbached16ec42011-08-29 22:24:09 +00004401 // The instruction must be predicable.
4402 if (!MCID.isPredicable())
4403 return Error(Loc, "instructions in IT block must be predicable");
4404 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4405 unsigned ITCond = bit ? ITState.Cond :
4406 ARMCC::getOppositeCondition(ITState.Cond);
4407 if (Cond != ITCond) {
4408 // Find the condition code Operand to get its SMLoc information.
4409 SMLoc CondLoc;
4410 for (unsigned i = 1; i < Operands.size(); ++i)
4411 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4412 CondLoc = Operands[i]->getStartLoc();
4413 return Error(CondLoc, "incorrect condition in IT block; got '" +
4414 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4415 "', but expected '" +
4416 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4417 }
Jim Grosbachc61fc8f2011-08-31 18:29:05 +00004418 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00004419 } else if (isThumbTwo() && MCID.isPredicable() &&
4420 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson29cfe6c2011-09-09 21:48:23 +00004421 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4422 Inst.getOpcode() != ARM::t2B)
Jim Grosbached16ec42011-08-29 22:24:09 +00004423 return Error(Loc, "predicated instructions must be in IT block");
4424
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004425 switch (Inst.getOpcode()) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00004426 case ARM::LDRD:
4427 case ARM::LDRD_PRE:
4428 case ARM::LDRD_POST:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004429 case ARM::LDREXD: {
4430 // Rt2 must be Rt + 1.
4431 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4432 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4433 if (Rt2 != Rt + 1)
4434 return Error(Operands[3]->getStartLoc(),
4435 "destination operands must be sequential");
4436 return false;
4437 }
Jim Grosbacheb09f492011-08-11 20:28:23 +00004438 case ARM::STRD: {
4439 // Rt2 must be Rt + 1.
4440 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4441 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4442 if (Rt2 != Rt + 1)
4443 return Error(Operands[3]->getStartLoc(),
4444 "source operands must be sequential");
4445 return false;
4446 }
Jim Grosbachf7164b22011-08-10 20:49:18 +00004447 case ARM::STRD_PRE:
4448 case ARM::STRD_POST:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004449 case ARM::STREXD: {
4450 // Rt2 must be Rt + 1.
4451 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4452 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
4453 if (Rt2 != Rt + 1)
Jim Grosbacheb09f492011-08-11 20:28:23 +00004454 return Error(Operands[3]->getStartLoc(),
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004455 "source operands must be sequential");
4456 return false;
4457 }
Jim Grosbach03f56d92011-07-27 21:09:25 +00004458 case ARM::SBFX:
4459 case ARM::UBFX: {
4460 // width must be in range [1, 32-lsb]
4461 unsigned lsb = Inst.getOperand(2).getImm();
4462 unsigned widthm1 = Inst.getOperand(3).getImm();
4463 if (widthm1 >= 32 - lsb)
4464 return Error(Operands[5]->getStartLoc(),
4465 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach64610e52011-08-16 21:42:31 +00004466 return false;
Jim Grosbach03f56d92011-07-27 21:09:25 +00004467 }
Jim Grosbach90103cc2011-08-18 21:50:53 +00004468 case ARM::tLDMIA: {
Jim Grosbacha31f2232011-09-07 18:05:34 +00004469 // If we're parsing Thumb2, the .w variant is available and handles
4470 // most cases that are normally illegal for a Thumb1 LDM
4471 // instruction. We'll make the transformation in processInstruction()
4472 // if necessary.
4473 //
Jim Grosbach90103cc2011-08-18 21:50:53 +00004474 // Thumb LDM instructions are writeback iff the base register is not
4475 // in the register list.
4476 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach139acd22011-08-22 23:01:07 +00004477 bool hasWritebackToken =
4478 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4479 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbach169b2be2011-08-23 18:13:04 +00004480 bool listContainsBase;
Jim Grosbacha31f2232011-09-07 18:05:34 +00004481 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00004482 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4483 "registers must be in range r0-r7");
Jim Grosbach90103cc2011-08-18 21:50:53 +00004484 // If we should have writeback, then there should be a '!' token.
Jim Grosbacha31f2232011-09-07 18:05:34 +00004485 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach90103cc2011-08-18 21:50:53 +00004486 return Error(Operands[2]->getStartLoc(),
4487 "writeback operator '!' expected");
Jim Grosbacha31f2232011-09-07 18:05:34 +00004488 // If we should not have writeback, there must not be a '!'. This is
4489 // true even for the 32-bit wide encodings.
Jim Grosbach169b2be2011-08-23 18:13:04 +00004490 if (listContainsBase && hasWritebackToken)
Jim Grosbach139acd22011-08-22 23:01:07 +00004491 return Error(Operands[3]->getStartLoc(),
4492 "writeback operator '!' not allowed when base register "
4493 "in register list");
Jim Grosbach90103cc2011-08-18 21:50:53 +00004494
4495 break;
4496 }
Jim Grosbacha31f2232011-09-07 18:05:34 +00004497 case ARM::t2LDMIA_UPD: {
4498 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
4499 return Error(Operands[4]->getStartLoc(),
4500 "writeback operator '!' not allowed when base register "
4501 "in register list");
4502 break;
4503 }
Jim Grosbach38c59fc2011-08-22 23:17:34 +00004504 case ARM::tPOP: {
Jim Grosbach169b2be2011-08-23 18:13:04 +00004505 bool listContainsBase;
4506 if (checkLowRegisterList(Inst, 3, 0, ARM::PC, listContainsBase))
4507 return Error(Operands[2]->getStartLoc(),
4508 "registers must be in range r0-r7 or pc");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00004509 break;
4510 }
4511 case ARM::tPUSH: {
Jim Grosbach169b2be2011-08-23 18:13:04 +00004512 bool listContainsBase;
4513 if (checkLowRegisterList(Inst, 3, 0, ARM::LR, listContainsBase))
4514 return Error(Operands[2]->getStartLoc(),
4515 "registers must be in range r0-r7 or lr");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00004516 break;
4517 }
Jim Grosbachd80d1692011-08-23 18:15:37 +00004518 case ARM::tSTMIA_UPD: {
4519 bool listContainsBase;
Jim Grosbach099c9762011-09-16 20:50:13 +00004520 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachd80d1692011-08-23 18:15:37 +00004521 return Error(Operands[4]->getStartLoc(),
4522 "registers must be in range r0-r7");
4523 break;
4524 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004525 }
4526
4527 return false;
4528}
4529
Jim Grosbach8ba76c62011-08-11 17:35:48 +00004530void ARMAsmParser::
4531processInstruction(MCInst &Inst,
4532 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4533 switch (Inst.getOpcode()) {
4534 case ARM::LDMIA_UPD:
4535 // If this is a load of a single register via a 'pop', then we should use
4536 // a post-indexed LDR instruction instead, per the ARM ARM.
4537 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
4538 Inst.getNumOperands() == 5) {
4539 MCInst TmpInst;
4540 TmpInst.setOpcode(ARM::LDR_POST_IMM);
4541 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4542 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4543 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4544 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
4545 TmpInst.addOperand(MCOperand::CreateImm(4));
4546 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4547 TmpInst.addOperand(Inst.getOperand(3));
4548 Inst = TmpInst;
4549 }
4550 break;
Jim Grosbach27ad83d2011-08-11 18:07:11 +00004551 case ARM::STMDB_UPD:
4552 // If this is a store of a single register via a 'push', then we should use
4553 // a pre-indexed STR instruction instead, per the ARM ARM.
4554 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
4555 Inst.getNumOperands() == 5) {
4556 MCInst TmpInst;
4557 TmpInst.setOpcode(ARM::STR_PRE_IMM);
4558 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4559 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4560 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
4561 TmpInst.addOperand(MCOperand::CreateImm(-4));
4562 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4563 TmpInst.addOperand(Inst.getOperand(3));
4564 Inst = TmpInst;
4565 }
4566 break;
Jim Grosbache9ab47a2011-08-16 23:57:34 +00004567 case ARM::tADDi8:
Jim Grosbach6d606fb2011-08-31 17:07:33 +00004568 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4569 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4570 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4571 // to encoding T1 if <Rd> is omitted."
4572 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
Jim Grosbache9ab47a2011-08-16 23:57:34 +00004573 Inst.setOpcode(ARM::tADDi3);
4574 break;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004575 case ARM::tSUBi8:
4576 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4577 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4578 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4579 // to encoding T1 if <Rd> is omitted."
4580 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
4581 Inst.setOpcode(ARM::tSUBi3);
4582 break;
Owen Anderson29cfe6c2011-09-09 21:48:23 +00004583 case ARM::tB:
4584 // A Thumb conditional branch outside of an IT block is a tBcc.
4585 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4586 Inst.setOpcode(ARM::tBcc);
4587 break;
4588 case ARM::t2B:
4589 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
4590 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4591 Inst.setOpcode(ARM::t2Bcc);
4592 break;
Jim Grosbach99bc8462011-08-31 21:17:31 +00004593 case ARM::t2Bcc:
Jim Grosbacha0d34d32011-09-02 23:22:08 +00004594 // If the conditional is AL or we're in an IT block, we really want t2B.
4595 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock())
Jim Grosbach99bc8462011-08-31 21:17:31 +00004596 Inst.setOpcode(ARM::t2B);
4597 break;
Jim Grosbachcbd4ab12011-08-17 22:57:40 +00004598 case ARM::tBcc:
4599 // If the conditional is AL, we really want tB.
4600 if (Inst.getOperand(1).getImm() == ARMCC::AL)
4601 Inst.setOpcode(ARM::tB);
Jim Grosbach6ddb5682011-08-18 16:08:39 +00004602 break;
Jim Grosbacha31f2232011-09-07 18:05:34 +00004603 case ARM::tLDMIA: {
4604 // If the register list contains any high registers, or if the writeback
4605 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
4606 // instead if we're in Thumb2. Otherwise, this should have generated
4607 // an error in validateInstruction().
4608 unsigned Rn = Inst.getOperand(0).getReg();
4609 bool hasWritebackToken =
4610 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4611 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
4612 bool listContainsBase;
4613 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
4614 (!listContainsBase && !hasWritebackToken) ||
4615 (listContainsBase && hasWritebackToken)) {
4616 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4617 assert (isThumbTwo());
4618 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
4619 // If we're switching to the updating version, we need to insert
4620 // the writeback tied operand.
4621 if (hasWritebackToken)
4622 Inst.insert(Inst.begin(),
4623 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
4624 }
4625 break;
4626 }
Jim Grosbach099c9762011-09-16 20:50:13 +00004627 case ARM::tSTMIA_UPD: {
4628 // If the register list contains any high registers, we need to use
4629 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
4630 // should have generated an error in validateInstruction().
4631 unsigned Rn = Inst.getOperand(0).getReg();
4632 bool listContainsBase;
4633 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
4634 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4635 assert (isThumbTwo());
4636 Inst.setOpcode(ARM::t2STMIA_UPD);
4637 }
4638 break;
4639 }
Jim Grosbachb908b7a2011-09-10 00:15:36 +00004640 case ARM::t2MOVi: {
4641 // If we can use the 16-bit encoding and the user didn't explicitly
4642 // request the 32-bit variant, transform it here.
4643 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4644 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbach18b8b172011-09-14 19:12:11 +00004645 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
4646 Inst.getOperand(4).getReg() == ARM::CPSR) ||
4647 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbachb908b7a2011-09-10 00:15:36 +00004648 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4649 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4650 // The operands aren't in the same order for tMOVi8...
4651 MCInst TmpInst;
4652 TmpInst.setOpcode(ARM::tMOVi8);
4653 TmpInst.addOperand(Inst.getOperand(0));
4654 TmpInst.addOperand(Inst.getOperand(4));
4655 TmpInst.addOperand(Inst.getOperand(1));
4656 TmpInst.addOperand(Inst.getOperand(2));
4657 TmpInst.addOperand(Inst.getOperand(3));
4658 Inst = TmpInst;
4659 }
4660 break;
4661 }
4662 case ARM::t2MOVr: {
4663 // If we can use the 16-bit encoding and the user didn't explicitly
4664 // request the 32-bit variant, transform it here.
4665 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4666 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4667 Inst.getOperand(2).getImm() == ARMCC::AL &&
4668 Inst.getOperand(4).getReg() == ARM::CPSR &&
4669 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4670 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4671 // The operands aren't the same for tMOV[S]r... (no cc_out)
4672 MCInst TmpInst;
4673 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
4674 TmpInst.addOperand(Inst.getOperand(0));
4675 TmpInst.addOperand(Inst.getOperand(1));
4676 TmpInst.addOperand(Inst.getOperand(2));
4677 TmpInst.addOperand(Inst.getOperand(3));
4678 Inst = TmpInst;
4679 }
4680 break;
4681 }
Jim Grosbach82213192011-09-19 20:29:33 +00004682 case ARM::t2SXTH:
Jim Grosbachb3519802011-09-20 00:46:54 +00004683 case ARM::t2SXTB:
4684 case ARM::t2UXTH:
4685 case ARM::t2UXTB: {
Jim Grosbach82213192011-09-19 20:29:33 +00004686 // If we can use the 16-bit encoding and the user didn't explicitly
4687 // request the 32-bit variant, transform it here.
4688 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4689 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4690 Inst.getOperand(2).getImm() == 0 &&
4691 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4692 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbachb3519802011-09-20 00:46:54 +00004693 unsigned NewOpc;
4694 switch (Inst.getOpcode()) {
4695 default: llvm_unreachable("Illegal opcode!");
4696 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
4697 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
4698 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
4699 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
4700 }
Jim Grosbach82213192011-09-19 20:29:33 +00004701 // The operands aren't the same for thumb1 (no rotate operand).
4702 MCInst TmpInst;
4703 TmpInst.setOpcode(NewOpc);
4704 TmpInst.addOperand(Inst.getOperand(0));
4705 TmpInst.addOperand(Inst.getOperand(1));
4706 TmpInst.addOperand(Inst.getOperand(3));
4707 TmpInst.addOperand(Inst.getOperand(4));
4708 Inst = TmpInst;
4709 }
4710 break;
4711 }
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004712 case ARM::t2IT: {
4713 // The mask bits for all but the first condition are represented as
4714 // the low bit of the condition code value implies 't'. We currently
4715 // always have 1 implies 't', so XOR toggle the bits if the low bit
4716 // of the condition code is zero. The encoding also expects the low
4717 // bit of the condition to be encoded as bit 4 of the mask operand,
4718 // so mask that in if needed
4719 MCOperand &MO = Inst.getOperand(1);
4720 unsigned Mask = MO.getImm();
Jim Grosbached16ec42011-08-29 22:24:09 +00004721 unsigned OrigMask = Mask;
4722 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004723 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004724 assert(Mask && TZ <= 3 && "illegal IT mask value!");
4725 for (unsigned i = 3; i != TZ; --i)
4726 Mask ^= 1 << i;
4727 } else
4728 Mask |= 0x10;
4729 MO.setImm(Mask);
Jim Grosbached16ec42011-08-29 22:24:09 +00004730
4731 // Set up the IT block state according to the IT instruction we just
4732 // matched.
4733 assert(!inITBlock() && "nested IT blocks?!");
4734 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
4735 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
4736 ITState.CurPosition = 0;
4737 ITState.FirstCond = true;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004738 break;
4739 }
Jim Grosbach8ba76c62011-08-11 17:35:48 +00004740 }
4741}
4742
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004743unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
4744 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
4745 // suffix depending on whether they're in an IT block or not.
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00004746 unsigned Opc = Inst.getOpcode();
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00004747 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004748 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
4749 assert(MCID.hasOptionalDef() &&
4750 "optionally flag setting instruction missing optional def operand");
4751 assert(MCID.NumOperands == Inst.getNumOperands() &&
4752 "operand count mismatch!");
4753 // Find the optional-def operand (cc_out).
4754 unsigned OpNo;
4755 for (OpNo = 0;
4756 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
4757 ++OpNo)
4758 ;
4759 // If we're parsing Thumb1, reject it completely.
4760 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
4761 return Match_MnemonicFail;
4762 // If we're parsing Thumb2, which form is legal depends on whether we're
4763 // in an IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00004764 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
4765 !inITBlock())
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004766 return Match_RequiresITBlock;
Jim Grosbached16ec42011-08-29 22:24:09 +00004767 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
4768 inITBlock())
4769 return Match_RequiresNotITBlock;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004770 }
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00004771 // Some high-register supporting Thumb1 encodings only allow both registers
4772 // to be from r0-r7 when in Thumb2.
4773 else if (Opc == ARM::tADDhirr && isThumbOne() &&
4774 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4775 isARMLowRegister(Inst.getOperand(2).getReg()))
4776 return Match_RequiresThumb2;
4777 // Others only require ARMv6 or later.
Jim Grosbachf86cd372011-08-19 20:46:54 +00004778 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00004779 isARMLowRegister(Inst.getOperand(0).getReg()) &&
4780 isARMLowRegister(Inst.getOperand(1).getReg()))
4781 return Match_RequiresV6;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004782 return Match_Success;
4783}
4784
Chris Lattner9487de62010-10-28 21:28:01 +00004785bool ARMAsmParser::
4786MatchAndEmitInstruction(SMLoc IDLoc,
4787 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
4788 MCStreamer &Out) {
4789 MCInst Inst;
4790 unsigned ErrorInfo;
Jim Grosbach120a96a2011-08-15 23:03:29 +00004791 unsigned MatchResult;
Kevin Enderby3164a342010-12-09 19:19:43 +00004792 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby3164a342010-12-09 19:19:43 +00004793 switch (MatchResult) {
Jim Grosbach120a96a2011-08-15 23:03:29 +00004794 default: break;
Chris Lattnerd27b05e2010-10-28 21:41:58 +00004795 case Match_Success:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004796 // Context sensitive operand constraints aren't handled by the matcher,
4797 // so check them here.
Jim Grosbacha0d34d32011-09-02 23:22:08 +00004798 if (validateInstruction(Inst, Operands)) {
4799 // Still progress the IT block, otherwise one wrong condition causes
4800 // nasty cascading errors.
4801 forwardITPosition();
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004802 return true;
Jim Grosbacha0d34d32011-09-02 23:22:08 +00004803 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004804
Jim Grosbach8ba76c62011-08-11 17:35:48 +00004805 // Some instructions need post-processing to, for example, tweak which
4806 // encoding is selected.
4807 processInstruction(Inst, Operands);
4808
Jim Grosbacha0d34d32011-09-02 23:22:08 +00004809 // Only move forward at the very end so that everything in validate
4810 // and process gets a consistent answer about whether we're in an IT
4811 // block.
4812 forwardITPosition();
4813
Chris Lattner9487de62010-10-28 21:28:01 +00004814 Out.EmitInstruction(Inst);
4815 return false;
Chris Lattnerd27b05e2010-10-28 21:41:58 +00004816 case Match_MissingFeature:
4817 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
4818 return true;
4819 case Match_InvalidOperand: {
4820 SMLoc ErrorLoc = IDLoc;
4821 if (ErrorInfo != ~0U) {
4822 if (ErrorInfo >= Operands.size())
4823 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach624bcc72010-10-29 14:46:02 +00004824
Chris Lattnerd27b05e2010-10-28 21:41:58 +00004825 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
4826 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
4827 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00004828
Chris Lattnerd27b05e2010-10-28 21:41:58 +00004829 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattner9487de62010-10-28 21:28:01 +00004830 }
Chris Lattnerd27b05e2010-10-28 21:41:58 +00004831 case Match_MnemonicFail:
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004832 return Error(IDLoc, "invalid instruction");
Daniel Dunbar66193402011-02-04 17:12:23 +00004833 case Match_ConversionFail:
Jim Grosbach8e048492011-08-19 22:07:46 +00004834 // The converter function will have already emited a diagnostic.
4835 return true;
Jim Grosbached16ec42011-08-29 22:24:09 +00004836 case Match_RequiresNotITBlock:
4837 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004838 case Match_RequiresITBlock:
4839 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00004840 case Match_RequiresV6:
4841 return Error(IDLoc, "instruction variant requires ARMv6 or later");
4842 case Match_RequiresThumb2:
4843 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnerd27b05e2010-10-28 21:41:58 +00004844 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00004845
Eric Christopher91d7b902010-10-29 09:26:59 +00004846 llvm_unreachable("Implement any new match types added!");
Bill Wendlingee7f1f92010-11-06 21:42:12 +00004847 return true;
Chris Lattner9487de62010-10-28 21:28:01 +00004848}
4849
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004850/// parseDirective parses the arm specific directives
Kevin Enderbyccab3172009-09-15 00:27:25 +00004851bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
4852 StringRef IDVal = DirectiveID.getIdentifier();
4853 if (IDVal == ".word")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004854 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00004855 else if (IDVal == ".thumb")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004856 return parseDirectiveThumb(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00004857 else if (IDVal == ".thumb_func")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004858 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00004859 else if (IDVal == ".code")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004860 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00004861 else if (IDVal == ".syntax")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004862 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyccab3172009-09-15 00:27:25 +00004863 return true;
4864}
4865
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004866/// parseDirectiveWord
Kevin Enderbyccab3172009-09-15 00:27:25 +00004867/// ::= .word [ expression (, expression)* ]
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004868bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyccab3172009-09-15 00:27:25 +00004869 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4870 for (;;) {
4871 const MCExpr *Value;
4872 if (getParser().ParseExpression(Value))
4873 return true;
4874
Chris Lattnerc35681b2010-01-19 19:46:13 +00004875 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyccab3172009-09-15 00:27:25 +00004876
4877 if (getLexer().is(AsmToken::EndOfStatement))
4878 break;
Jim Grosbach624bcc72010-10-29 14:46:02 +00004879
Kevin Enderbyccab3172009-09-15 00:27:25 +00004880 // FIXME: Improve diagnostic.
4881 if (getLexer().isNot(AsmToken::Comma))
4882 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004883 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00004884 }
4885 }
4886
Sean Callanana83fd7d2010-01-19 20:27:46 +00004887 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00004888 return false;
4889}
4890
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004891/// parseDirectiveThumb
Kevin Enderby146dcf22009-10-15 20:48:48 +00004892/// ::= .thumb
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004893bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby146dcf22009-10-15 20:48:48 +00004894 if (getLexer().isNot(AsmToken::EndOfStatement))
4895 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004896 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004897
4898 // TODO: set thumb mode
4899 // TODO: tell the MC streamer the mode
4900 // getParser().getStreamer().Emit???();
4901 return false;
4902}
4903
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004904/// parseDirectiveThumbFunc
Kevin Enderby146dcf22009-10-15 20:48:48 +00004905/// ::= .thumbfunc symbol_name
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004906bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00004907 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
4908 bool isMachO = MAI.hasSubsectionsViaSymbols();
4909 StringRef Name;
4910
4911 // Darwin asm has function name after .thumb_func direction
4912 // ELF doesn't
4913 if (isMachO) {
4914 const AsmToken &Tok = Parser.getTok();
4915 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
4916 return Error(L, "unexpected token in .thumb_func directive");
4917 Name = Tok.getString();
4918 Parser.Lex(); // Consume the identifier token.
4919 }
4920
Kevin Enderby146dcf22009-10-15 20:48:48 +00004921 if (getLexer().isNot(AsmToken::EndOfStatement))
4922 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004923 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004924
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00004925 // FIXME: assuming function name will be the line following .thumb_func
4926 if (!isMachO) {
4927 Name = Parser.getTok().getString();
4928 }
4929
Jim Grosbachc6db8ce2010-11-05 22:33:53 +00004930 // Mark symbol as a thumb symbol.
4931 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
4932 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby146dcf22009-10-15 20:48:48 +00004933 return false;
4934}
4935
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004936/// parseDirectiveSyntax
Kevin Enderby146dcf22009-10-15 20:48:48 +00004937/// ::= .syntax unified | divided
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004938bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00004939 const AsmToken &Tok = Parser.getTok();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004940 if (Tok.isNot(AsmToken::Identifier))
4941 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer92d89982010-07-14 22:38:02 +00004942 StringRef Mode = Tok.getString();
Duncan Sands257eba42010-06-29 13:04:35 +00004943 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callanana83fd7d2010-01-19 20:27:46 +00004944 Parser.Lex();
Duncan Sands257eba42010-06-29 13:04:35 +00004945 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderbye9f2f0c2011-01-27 23:22:36 +00004946 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby146dcf22009-10-15 20:48:48 +00004947 else
4948 return Error(L, "unrecognized syntax mode in .syntax directive");
4949
4950 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan936b0d32010-01-19 21:44:56 +00004951 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004952 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004953
4954 // TODO tell the MC streamer the mode
4955 // getParser().getStreamer().Emit???();
4956 return false;
4957}
4958
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004959/// parseDirectiveCode
Kevin Enderby146dcf22009-10-15 20:48:48 +00004960/// ::= .code 16 | 32
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004961bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00004962 const AsmToken &Tok = Parser.getTok();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004963 if (Tok.isNot(AsmToken::Integer))
4964 return Error(L, "unexpected token in .code directive");
Sean Callanan936b0d32010-01-19 21:44:56 +00004965 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands257eba42010-06-29 13:04:35 +00004966 if (Val == 16)
Sean Callanana83fd7d2010-01-19 20:27:46 +00004967 Parser.Lex();
Duncan Sands257eba42010-06-29 13:04:35 +00004968 else if (Val == 32)
Sean Callanana83fd7d2010-01-19 20:27:46 +00004969 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004970 else
4971 return Error(L, "invalid operand to .code directive");
4972
4973 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan936b0d32010-01-19 21:44:56 +00004974 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004975 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004976
Evan Cheng284b4672011-07-08 22:36:29 +00004977 if (Val == 16) {
Jim Grosbachf471ac32011-09-06 18:46:23 +00004978 if (!isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00004979 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00004980 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng284b4672011-07-08 22:36:29 +00004981 } else {
Jim Grosbachf471ac32011-09-06 18:46:23 +00004982 if (isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00004983 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00004984 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Cheng45543ba2011-07-08 22:49:55 +00004985 }
Jim Grosbach2db0ea02010-11-05 22:40:53 +00004986
Kevin Enderby146dcf22009-10-15 20:48:48 +00004987 return false;
4988}
4989
Sean Callanan643a5572010-04-07 20:29:34 +00004990extern "C" void LLVMInitializeARMAsmLexer();
4991
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004992/// Force static initialization.
Kevin Enderbyccab3172009-09-15 00:27:25 +00004993extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng11424442011-07-26 00:24:13 +00004994 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
4995 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan643a5572010-04-07 20:29:34 +00004996 LLVMInitializeARMAsmLexer();
Kevin Enderbyccab3172009-09-15 00:27:25 +00004997}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00004998
Chris Lattner3e4582a2010-09-06 19:11:01 +00004999#define GET_REGISTER_MATCHER
5000#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00005001#include "ARMGenAsmMatcher.inc"