blob: 2e0c0fcca55068faaa0bebdfb92307b6353089f1 [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"
Daniel Dunbar188b47b2010-08-11 06:37:20 +000033#include "llvm/ADT/StringSwitch.h"
Chris Lattner00646cf2010-01-22 01:44:57 +000034#include "llvm/ADT/Twine.h"
Evan Cheng4d1ca962011-07-08 01:53:10 +000035
Kevin Enderbyccab3172009-09-15 00:27:25 +000036using namespace llvm;
37
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +000038namespace {
Bill Wendlingee7f1f92010-11-06 21:42:12 +000039
40class ARMOperand;
Jim Grosbach624bcc72010-10-29 14:46:02 +000041
Evan Cheng11424442011-07-26 00:24:13 +000042class ARMAsmParser : public MCTargetAsmParser {
Evan Cheng91111d22011-07-09 05:47:46 +000043 MCSubtargetInfo &STI;
Kevin Enderbyccab3172009-09-15 00:27:25 +000044 MCAsmParser &Parser;
45
Jim Grosbached16ec42011-08-29 22:24:09 +000046 struct {
47 ARMCC::CondCodes Cond; // Condition for IT block.
48 unsigned Mask:4; // Condition mask for instructions.
49 // Starting at first 1 (from lsb).
50 // '1' condition as indicated in IT.
51 // '0' inverse of condition (else).
52 // Count of instructions in IT block is
53 // 4 - trailingzeroes(mask)
54
55 bool FirstCond; // Explicit flag for when we're parsing the
56 // First instruction in the IT block. It's
57 // implied in the mask, so needs special
58 // handling.
59
60 unsigned CurPosition; // Current position in parsing of IT
61 // block. In range [0,3]. Initialized
62 // according to count of instructions in block.
63 // ~0U if no active IT block.
64 } ITState;
65 bool inITBlock() { return ITState.CurPosition != ~0U;}
Jim Grosbacha0d34d32011-09-02 23:22:08 +000066 void forwardITPosition() {
67 if (!inITBlock()) return;
68 // Move to the next instruction in the IT block, if there is one. If not,
69 // mark the block as done.
70 unsigned TZ = CountTrailingZeros_32(ITState.Mask);
71 if (++ITState.CurPosition == 5 - TZ)
72 ITState.CurPosition = ~0U; // Done with the IT block after this.
73 }
Jim Grosbached16ec42011-08-29 22:24:09 +000074
75
Kevin Enderbyccab3172009-09-15 00:27:25 +000076 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyccab3172009-09-15 00:27:25 +000077 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
78
79 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
Kevin Enderbyccab3172009-09-15 00:27:25 +000080 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
81
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000082 int tryParseRegister();
83 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d6022d2011-07-26 20:41:24 +000084 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000085 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd3595712011-08-03 23:50:40 +000086 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000087 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
88 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbachd3595712011-08-03 23:50:40 +000089 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
90 unsigned &ShiftAmount);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000091 bool parseDirectiveWord(unsigned Size, SMLoc L);
92 bool parseDirectiveThumb(SMLoc L);
93 bool parseDirectiveThumbFunc(SMLoc L);
94 bool parseDirectiveCode(SMLoc L);
95 bool parseDirectiveSyntax(SMLoc L);
Kevin Enderby146dcf22009-10-15 20:48:48 +000096
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000097 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach3d1eac82011-08-26 21:43:41 +000098 bool &CarrySetting, unsigned &ProcessorIMod,
99 StringRef &ITMask);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000100 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +0000101 bool &CanAcceptPredicationCode);
Jim Grosbach624bcc72010-10-29 14:46:02 +0000102
Evan Cheng4d1ca962011-07-08 01:53:10 +0000103 bool isThumb() const {
104 // FIXME: Can tablegen auto-generate this?
Evan Cheng91111d22011-07-09 05:47:46 +0000105 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000106 }
Evan Cheng4d1ca962011-07-08 01:53:10 +0000107 bool isThumbOne() const {
Evan Cheng91111d22011-07-09 05:47:46 +0000108 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000109 }
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000110 bool isThumbTwo() const {
111 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
112 }
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000113 bool hasV6Ops() const {
114 return STI.getFeatureBits() & ARM::HasV6Ops;
115 }
James Molloy21efa7d2011-09-28 14:21:38 +0000116 bool hasV7Ops() const {
117 return STI.getFeatureBits() & ARM::HasV7Ops;
118 }
Evan Cheng284b4672011-07-08 22:36:29 +0000119 void SwitchMode() {
Evan Cheng91111d22011-07-09 05:47:46 +0000120 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
121 setAvailableFeatures(FB);
Evan Cheng284b4672011-07-08 22:36:29 +0000122 }
James Molloy21efa7d2011-09-28 14:21:38 +0000123 bool isMClass() const {
124 return STI.getFeatureBits() & ARM::FeatureMClass;
125 }
Evan Cheng4d1ca962011-07-08 01:53:10 +0000126
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000127 /// @name Auto-generated Match Functions
128 /// {
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +0000129
Chris Lattner3e4582a2010-09-06 19:11:01 +0000130#define GET_ASSEMBLER_HEADER
131#include "ARMGenAsmMatcher.inc"
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000132
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000133 /// }
134
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000135 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000136 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbach861e49c2011-02-12 01:34:40 +0000137 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000138 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbach861e49c2011-02-12 01:34:40 +0000139 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach48399582011-10-12 17:34:41 +0000140 OperandMatchResultTy parseCoprocOptionOperand(
141 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000142 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopescdd20af2011-02-18 19:49:06 +0000143 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000144 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopescdd20af2011-02-18 19:49:06 +0000145 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000146 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopescdd20af2011-02-18 19:49:06 +0000147 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach27c1e252011-07-21 17:23:04 +0000148 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
149 StringRef Op, int Low, int High);
150 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
151 return parsePKHImm(O, "lsl", 0, 31);
152 }
153 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
154 return parsePKHImm(O, "asr", 1, 32);
155 }
Jim Grosbach0a547702011-07-22 17:44:50 +0000156 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000157 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach833b9d32011-07-27 20:15:40 +0000158 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach864b6092011-07-28 21:34:26 +0000159 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachd3595712011-08-03 23:50:40 +0000160 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach1d9d5e92011-08-10 21:56:18 +0000161 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbache7fbce72011-10-03 23:38:36 +0000162 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000163 OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000164
165 // Asm Match Converter Methods
Jim Grosbach7db8d692011-09-08 22:07:06 +0000166 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
167 const SmallVectorImpl<MCParsedAsmOperand*> &);
168 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
169 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachc086f682011-09-08 00:39:19 +0000170 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
171 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach9c0b86a2011-09-16 21:55:56 +0000172 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
173 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000174 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000175 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson16d33f32011-08-26 20:43:14 +0000176 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
177 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd564bf32011-08-11 19:22:40 +0000178 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
179 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000180 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000181 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd886f8c2011-08-11 21:17:22 +0000182 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
183 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd3595712011-08-03 23:50:40 +0000184 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
185 const SmallVectorImpl<MCParsedAsmOperand*> &);
186 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
187 const SmallVectorImpl<MCParsedAsmOperand*> &);
188 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
189 const SmallVectorImpl<MCParsedAsmOperand*> &);
190 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
191 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach5b96b802011-08-10 20:29:19 +0000192 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
193 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheb09f492011-08-11 20:28:23 +0000194 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
195 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachcd4dd252011-08-10 22:42:16 +0000196 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
197 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach8e048492011-08-19 22:07:46 +0000198 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
199 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach3ea06572011-10-24 22:16:58 +0000200 bool cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
201 const SmallVectorImpl<MCParsedAsmOperand*> &);
202 bool cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
203 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach05df4602011-10-31 21:50:31 +0000204 bool cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
205 const SmallVectorImpl<MCParsedAsmOperand*> &);
206 bool cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
207 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000208
209 bool validateInstruction(MCInst &Inst,
210 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachafad0532011-11-10 23:42:14 +0000211 bool processInstruction(MCInst &Inst,
Jim Grosbach8ba76c62011-08-11 17:35:48 +0000212 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach7283da92011-08-16 21:12:37 +0000213 bool shouldOmitCCOutOperand(StringRef Mnemonic,
214 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000215
Kevin Enderbyccab3172009-09-15 00:27:25 +0000216public:
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000217 enum ARMMatchResultTy {
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000218 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbached16ec42011-08-29 22:24:09 +0000219 Match_RequiresNotITBlock,
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000220 Match_RequiresV6,
221 Match_RequiresThumb2
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000222 };
223
Evan Cheng91111d22011-07-09 05:47:46 +0000224 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng11424442011-07-26 00:24:13 +0000225 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Cheng4d1ca962011-07-08 01:53:10 +0000226 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng284b4672011-07-08 22:36:29 +0000227
Evan Cheng4d1ca962011-07-08 01:53:10 +0000228 // Initialize the set of available features.
Evan Cheng91111d22011-07-09 05:47:46 +0000229 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbached16ec42011-08-29 22:24:09 +0000230
231 // Not in an ITBlock to start with.
232 ITState.CurPosition = ~0U;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000233 }
Kevin Enderbyccab3172009-09-15 00:27:25 +0000234
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000235 // Implementation of the MCTargetAsmParser interface:
236 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
237 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000238 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000239 bool ParseDirective(AsmToken DirectiveID);
240
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000241 unsigned checkTargetMatchPredicate(MCInst &Inst);
242
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000243 bool MatchAndEmitInstruction(SMLoc IDLoc,
244 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
245 MCStreamer &Out);
Kevin Enderbyccab3172009-09-15 00:27:25 +0000246};
Jim Grosbach624bcc72010-10-29 14:46:02 +0000247} // end anonymous namespace
248
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +0000249namespace {
250
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000251/// ARMOperand - Instances of this class represent a parsed ARM machine
252/// instruction.
Bill Wendlingee7f1f92010-11-06 21:42:12 +0000253class ARMOperand : public MCParsedAsmOperand {
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000254 enum KindTy {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000255 k_CondCode,
256 k_CCOut,
257 k_ITCondMask,
258 k_CoprocNum,
259 k_CoprocReg,
Jim Grosbach48399582011-10-12 17:34:41 +0000260 k_CoprocOption,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000261 k_Immediate,
262 k_FPImmediate,
263 k_MemBarrierOpt,
264 k_Memory,
265 k_PostIndexRegister,
266 k_MSRMask,
267 k_ProcIFlags,
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000268 k_VectorIndex,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000269 k_Register,
270 k_RegisterList,
271 k_DPRRegisterList,
272 k_SPRRegisterList,
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000273 k_VectorList,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000274 k_ShiftedRegister,
275 k_ShiftedImmediate,
276 k_ShifterImmediate,
277 k_RotateImmediate,
278 k_BitfieldDescriptor,
279 k_Token
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000280 } Kind;
281
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000282 SMLoc StartLoc, EndLoc;
Bill Wendling0ab0f672010-11-18 21:50:54 +0000283 SmallVector<unsigned, 8> Registers;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000284
285 union {
286 struct {
Daniel Dunbard8042b72010-08-11 06:36:53 +0000287 ARMCC::CondCodes Val;
288 } CC;
289
290 struct {
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000291 unsigned Val;
292 } Cop;
293
294 struct {
Jim Grosbach48399582011-10-12 17:34:41 +0000295 unsigned Val;
296 } CoprocOption;
297
298 struct {
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000299 unsigned Mask:4;
300 } ITMask;
301
302 struct {
303 ARM_MB::MemBOpt Val;
304 } MBOpt;
305
306 struct {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000307 ARM_PROC::IFlags Val;
308 } IFlags;
309
310 struct {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000311 unsigned Val;
312 } MMask;
313
314 struct {
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000315 const char *Data;
316 unsigned Length;
317 } Tok;
318
319 struct {
320 unsigned RegNum;
321 } Reg;
322
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000323 // A vector register list is a sequential list of 1 to 4 registers.
324 struct {
325 unsigned RegNum;
326 unsigned Count;
327 } VectorList;
328
Bill Wendlingb884a8e2010-11-06 22:19:43 +0000329 struct {
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000330 unsigned Val;
331 } VectorIndex;
332
333 struct {
Kevin Enderbyf5079942009-10-13 22:19:02 +0000334 const MCExpr *Val;
335 } Imm;
Jim Grosbach624bcc72010-10-29 14:46:02 +0000336
Jim Grosbache7fbce72011-10-03 23:38:36 +0000337 struct {
338 unsigned Val; // encoded 8-bit representation
339 } FPImm;
340
Daniel Dunbar2be732a2011-01-10 15:26:21 +0000341 /// Combined record for all forms of ARM address expressions.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000342 struct {
343 unsigned BaseRegNum;
Jim Grosbachd3595712011-08-03 23:50:40 +0000344 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
345 // was specified.
346 const MCConstantExpr *OffsetImm; // Offset immediate value
347 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
348 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbacha95ec992011-10-11 17:29:55 +0000349 unsigned ShiftImm; // shift for OffsetReg.
350 unsigned Alignment; // 0 = no alignment specified
351 // n = alignment in bytes (8, 16, or 32)
Jim Grosbachd3595712011-08-03 23:50:40 +0000352 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbach871dff72011-10-11 15:59:20 +0000353 } Memory;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000354
355 struct {
Jim Grosbachd3595712011-08-03 23:50:40 +0000356 unsigned RegNum;
Jim Grosbachc320c852011-08-05 21:28:30 +0000357 bool isAdd;
358 ARM_AM::ShiftOpc ShiftTy;
359 unsigned ShiftImm;
Jim Grosbachd3595712011-08-03 23:50:40 +0000360 } PostIdxReg;
361
362 struct {
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000363 bool isASR;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000364 unsigned Imm;
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000365 } ShifterImm;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000366 struct {
367 ARM_AM::ShiftOpc ShiftTy;
368 unsigned SrcReg;
369 unsigned ShiftReg;
370 unsigned ShiftImm;
Jim Grosbachac798e12011-07-25 20:49:51 +0000371 } RegShiftedReg;
Owen Andersonb595ed02011-07-21 18:54:16 +0000372 struct {
373 ARM_AM::ShiftOpc ShiftTy;
374 unsigned SrcReg;
375 unsigned ShiftImm;
Jim Grosbachac798e12011-07-25 20:49:51 +0000376 } RegShiftedImm;
Jim Grosbach833b9d32011-07-27 20:15:40 +0000377 struct {
378 unsigned Imm;
379 } RotImm;
Jim Grosbach864b6092011-07-28 21:34:26 +0000380 struct {
381 unsigned LSB;
382 unsigned Width;
383 } Bitfield;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000384 };
Jim Grosbach624bcc72010-10-29 14:46:02 +0000385
Bill Wendlingee7f1f92010-11-06 21:42:12 +0000386 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
387public:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000388 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
389 Kind = o.Kind;
390 StartLoc = o.StartLoc;
391 EndLoc = o.EndLoc;
392 switch (Kind) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000393 case k_CondCode:
Daniel Dunbard8042b72010-08-11 06:36:53 +0000394 CC = o.CC;
395 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000396 case k_ITCondMask:
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000397 ITMask = o.ITMask;
398 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000399 case k_Token:
Daniel Dunbard8042b72010-08-11 06:36:53 +0000400 Tok = o.Tok;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000401 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000402 case k_CCOut:
403 case k_Register:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000404 Reg = o.Reg;
405 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000406 case k_RegisterList:
407 case k_DPRRegisterList:
408 case k_SPRRegisterList:
Bill Wendling0ab0f672010-11-18 21:50:54 +0000409 Registers = o.Registers;
Bill Wendling7cef4472010-11-06 19:56:04 +0000410 break;
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000411 case k_VectorList:
412 VectorList = o.VectorList;
413 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000414 case k_CoprocNum:
415 case k_CoprocReg:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000416 Cop = o.Cop;
417 break;
Jim Grosbach48399582011-10-12 17:34:41 +0000418 case k_CoprocOption:
419 CoprocOption = o.CoprocOption;
420 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000421 case k_Immediate:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000422 Imm = o.Imm;
423 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000424 case k_FPImmediate:
Jim Grosbache7fbce72011-10-03 23:38:36 +0000425 FPImm = o.FPImm;
426 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000427 case k_MemBarrierOpt:
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000428 MBOpt = o.MBOpt;
429 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000430 case k_Memory:
Jim Grosbach871dff72011-10-11 15:59:20 +0000431 Memory = o.Memory;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000432 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000433 case k_PostIndexRegister:
Jim Grosbachd3595712011-08-03 23:50:40 +0000434 PostIdxReg = o.PostIdxReg;
435 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000436 case k_MSRMask:
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000437 MMask = o.MMask;
438 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000439 case k_ProcIFlags:
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000440 IFlags = o.IFlags;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000441 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000442 case k_ShifterImmediate:
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000443 ShifterImm = o.ShifterImm;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000444 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000445 case k_ShiftedRegister:
Jim Grosbachac798e12011-07-25 20:49:51 +0000446 RegShiftedReg = o.RegShiftedReg;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000447 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000448 case k_ShiftedImmediate:
Jim Grosbachac798e12011-07-25 20:49:51 +0000449 RegShiftedImm = o.RegShiftedImm;
Owen Andersonb595ed02011-07-21 18:54:16 +0000450 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000451 case k_RotateImmediate:
Jim Grosbach833b9d32011-07-27 20:15:40 +0000452 RotImm = o.RotImm;
453 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000454 case k_BitfieldDescriptor:
Jim Grosbach864b6092011-07-28 21:34:26 +0000455 Bitfield = o.Bitfield;
456 break;
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000457 case k_VectorIndex:
458 VectorIndex = o.VectorIndex;
459 break;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000460 }
461 }
Jim Grosbach624bcc72010-10-29 14:46:02 +0000462
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000463 /// getStartLoc - Get the location of the first token of this operand.
464 SMLoc getStartLoc() const { return StartLoc; }
465 /// getEndLoc - Get the location of the last token of this operand.
466 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000467
Daniel Dunbard8042b72010-08-11 06:36:53 +0000468 ARMCC::CondCodes getCondCode() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000469 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbard8042b72010-08-11 06:36:53 +0000470 return CC.Val;
471 }
472
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000473 unsigned getCoproc() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000474 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000475 return Cop.Val;
476 }
477
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000478 StringRef getToken() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000479 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000480 return StringRef(Tok.Data, Tok.Length);
481 }
482
483 unsigned getReg() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000484 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling2cae3272010-11-09 22:44:22 +0000485 return Reg.RegNum;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000486 }
487
Bill Wendlingbed94652010-11-09 23:28:44 +0000488 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000489 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
490 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling0ab0f672010-11-18 21:50:54 +0000491 return Registers;
Bill Wendling7cef4472010-11-06 19:56:04 +0000492 }
493
Kevin Enderbyf5079942009-10-13 22:19:02 +0000494 const MCExpr *getImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000495 assert(Kind == k_Immediate && "Invalid access!");
Kevin Enderbyf5079942009-10-13 22:19:02 +0000496 return Imm.Val;
497 }
498
Jim Grosbache7fbce72011-10-03 23:38:36 +0000499 unsigned getFPImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000500 assert(Kind == k_FPImmediate && "Invalid access!");
Jim Grosbache7fbce72011-10-03 23:38:36 +0000501 return FPImm.Val;
502 }
503
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000504 unsigned getVectorIndex() const {
505 assert(Kind == k_VectorIndex && "Invalid access!");
506 return VectorIndex.Val;
507 }
508
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000509 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000510 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000511 return MBOpt.Val;
512 }
513
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000514 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000515 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000516 return IFlags.Val;
517 }
518
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000519 unsigned getMSRMask() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000520 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000521 return MMask.Val;
522 }
523
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000524 bool isCoprocNum() const { return Kind == k_CoprocNum; }
525 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach48399582011-10-12 17:34:41 +0000526 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000527 bool isCondCode() const { return Kind == k_CondCode; }
528 bool isCCOut() const { return Kind == k_CCOut; }
529 bool isITMask() const { return Kind == k_ITCondMask; }
530 bool isITCondCode() const { return Kind == k_CondCode; }
531 bool isImm() const { return Kind == k_Immediate; }
532 bool isFPImm() const { return Kind == k_FPImmediate; }
Jim Grosbach7db8d692011-09-08 22:07:06 +0000533 bool isImm8s4() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000534 if (Kind != k_Immediate)
Jim Grosbach7db8d692011-09-08 22:07:06 +0000535 return false;
536 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
537 if (!CE) return false;
538 int64_t Value = CE->getValue();
539 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
540 }
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000541 bool isImm0_1020s4() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000542 if (Kind != k_Immediate)
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000543 return false;
544 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
545 if (!CE) return false;
546 int64_t Value = CE->getValue();
547 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
548 }
549 bool isImm0_508s4() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000550 if (Kind != k_Immediate)
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000551 return false;
552 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
553 if (!CE) return false;
554 int64_t Value = CE->getValue();
555 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
556 }
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000557 bool isImm0_255() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000558 if (Kind != k_Immediate)
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000559 return false;
560 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
561 if (!CE) return false;
562 int64_t Value = CE->getValue();
563 return Value >= 0 && Value < 256;
564 }
Jim Grosbach31756c22011-07-13 22:01:08 +0000565 bool isImm0_7() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000566 if (Kind != k_Immediate)
Jim Grosbach31756c22011-07-13 22:01:08 +0000567 return false;
568 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
569 if (!CE) return false;
570 int64_t Value = CE->getValue();
571 return Value >= 0 && Value < 8;
572 }
573 bool isImm0_15() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000574 if (Kind != k_Immediate)
Jim Grosbach31756c22011-07-13 22:01:08 +0000575 return false;
576 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
577 if (!CE) return false;
578 int64_t Value = CE->getValue();
579 return Value >= 0 && Value < 16;
580 }
Jim Grosbach72e7c4f2011-07-21 23:26:25 +0000581 bool isImm0_31() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000582 if (Kind != k_Immediate)
Jim Grosbach72e7c4f2011-07-21 23:26:25 +0000583 return false;
584 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
585 if (!CE) return false;
586 int64_t Value = CE->getValue();
587 return Value >= 0 && Value < 32;
588 }
Jim Grosbach475c6db2011-07-25 23:09:14 +0000589 bool isImm1_16() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000590 if (Kind != k_Immediate)
Jim Grosbach475c6db2011-07-25 23:09:14 +0000591 return false;
592 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
593 if (!CE) return false;
594 int64_t Value = CE->getValue();
595 return Value > 0 && Value < 17;
596 }
Jim Grosbach801e0a32011-07-22 23:16:18 +0000597 bool isImm1_32() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000598 if (Kind != k_Immediate)
Jim Grosbach801e0a32011-07-22 23:16:18 +0000599 return false;
600 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
601 if (!CE) return false;
602 int64_t Value = CE->getValue();
603 return Value > 0 && Value < 33;
604 }
Jim Grosbachc14871c2011-11-10 19:18:01 +0000605 bool isImm0_32() const {
606 if (Kind != k_Immediate)
607 return false;
608 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
609 if (!CE) return false;
610 int64_t Value = CE->getValue();
611 return Value >= 0 && Value < 33;
612 }
Jim Grosbach975b6412011-07-13 20:10:10 +0000613 bool isImm0_65535() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000614 if (Kind != k_Immediate)
Jim Grosbach975b6412011-07-13 20:10:10 +0000615 return false;
616 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
617 if (!CE) return false;
618 int64_t Value = CE->getValue();
619 return Value >= 0 && Value < 65536;
620 }
Jim Grosbach7c09e3c2011-07-19 19:13:28 +0000621 bool isImm0_65535Expr() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000622 if (Kind != k_Immediate)
Jim Grosbach7c09e3c2011-07-19 19:13:28 +0000623 return false;
624 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
625 // If it's not a constant expression, it'll generate a fixup and be
626 // handled later.
627 if (!CE) return true;
628 int64_t Value = CE->getValue();
629 return Value >= 0 && Value < 65536;
630 }
Jim Grosbachf1637842011-07-26 16:24:27 +0000631 bool isImm24bit() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000632 if (Kind != k_Immediate)
Jim Grosbachf1637842011-07-26 16:24:27 +0000633 return false;
634 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
635 if (!CE) return false;
636 int64_t Value = CE->getValue();
637 return Value >= 0 && Value <= 0xffffff;
638 }
Jim Grosbach46dd4132011-08-17 21:51:27 +0000639 bool isImmThumbSR() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000640 if (Kind != k_Immediate)
Jim Grosbach46dd4132011-08-17 21:51:27 +0000641 return false;
642 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
643 if (!CE) return false;
644 int64_t Value = CE->getValue();
645 return Value > 0 && Value < 33;
646 }
Jim Grosbach27c1e252011-07-21 17:23:04 +0000647 bool isPKHLSLImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000648 if (Kind != k_Immediate)
Jim Grosbach27c1e252011-07-21 17:23:04 +0000649 return false;
650 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
651 if (!CE) return false;
652 int64_t Value = CE->getValue();
653 return Value >= 0 && Value < 32;
654 }
655 bool isPKHASRImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000656 if (Kind != k_Immediate)
Jim Grosbach27c1e252011-07-21 17:23:04 +0000657 return false;
658 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
659 if (!CE) return false;
660 int64_t Value = CE->getValue();
661 return Value > 0 && Value <= 32;
662 }
Jim Grosbach9720dcf2011-07-19 16:50:30 +0000663 bool isARMSOImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000664 if (Kind != k_Immediate)
Jim Grosbach9720dcf2011-07-19 16:50:30 +0000665 return false;
666 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
667 if (!CE) return false;
668 int64_t Value = CE->getValue();
669 return ARM_AM::getSOImmVal(Value) != -1;
670 }
Jim Grosbach3d785ed2011-10-28 22:50:54 +0000671 bool isARMSOImmNot() const {
672 if (Kind != k_Immediate)
673 return false;
674 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
675 if (!CE) return false;
676 int64_t Value = CE->getValue();
677 return ARM_AM::getSOImmVal(~Value) != -1;
678 }
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000679 bool isT2SOImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000680 if (Kind != k_Immediate)
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000681 return false;
682 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
683 if (!CE) return false;
684 int64_t Value = CE->getValue();
685 return ARM_AM::getT2SOImmVal(Value) != -1;
686 }
Jim Grosbachb009a872011-10-28 22:36:30 +0000687 bool isT2SOImmNot() const {
688 if (Kind != k_Immediate)
689 return false;
690 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
691 if (!CE) return false;
692 int64_t Value = CE->getValue();
693 return ARM_AM::getT2SOImmVal(~Value) != -1;
694 }
Jim Grosbach0a547702011-07-22 17:44:50 +0000695 bool isSetEndImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000696 if (Kind != k_Immediate)
Jim Grosbach0a547702011-07-22 17:44:50 +0000697 return false;
698 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
699 if (!CE) return false;
700 int64_t Value = CE->getValue();
701 return Value == 1 || Value == 0;
702 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000703 bool isReg() const { return Kind == k_Register; }
704 bool isRegList() const { return Kind == k_RegisterList; }
705 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
706 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
707 bool isToken() const { return Kind == k_Token; }
708 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
709 bool isMemory() const { return Kind == k_Memory; }
710 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
711 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
712 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
713 bool isRotImm() const { return Kind == k_RotateImmediate; }
714 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
715 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachc320c852011-08-05 21:28:30 +0000716 bool isPostIdxReg() const {
Jim Grosbachee201fa2011-11-14 17:52:47 +0000717 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachc320c852011-08-05 21:28:30 +0000718 }
Jim Grosbacha95ec992011-10-11 17:29:55 +0000719 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachc11b7c32011-10-10 23:06:42 +0000720 if (!isMemory())
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000721 return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000722 // No offset of any kind.
Jim Grosbacha95ec992011-10-11 17:29:55 +0000723 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
724 (alignOK || Memory.Alignment == 0);
725 }
726 bool isAlignedMemory() const {
727 return isMemNoOffset(true);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000728 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000729 bool isAddrMode2() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000730 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000731 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000732 if (Memory.OffsetRegNum) return true;
Jim Grosbachd3595712011-08-03 23:50:40 +0000733 // Immediate offset in range [-4095, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +0000734 if (!Memory.OffsetImm) return true;
735 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachd3595712011-08-03 23:50:40 +0000736 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +0000737 }
Jim Grosbachcd17c122011-08-04 23:01:30 +0000738 bool isAM2OffsetImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000739 if (Kind != k_Immediate)
Jim Grosbachcd17c122011-08-04 23:01:30 +0000740 return false;
741 // Immediate offset in range [-4095, 4095].
742 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
743 if (!CE) return false;
744 int64_t Val = CE->getValue();
745 return Val > -4096 && Val < 4096;
746 }
Jim Grosbach5b96b802011-08-10 20:29:19 +0000747 bool isAddrMode3() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000748 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000749 // No shifts are legal for AM3.
Jim Grosbach871dff72011-10-11 15:59:20 +0000750 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000751 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000752 if (Memory.OffsetRegNum) return true;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000753 // Immediate offset in range [-255, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +0000754 if (!Memory.OffsetImm) return true;
755 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach5b96b802011-08-10 20:29:19 +0000756 return Val > -256 && Val < 256;
757 }
758 bool isAM3Offset() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000759 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach5b96b802011-08-10 20:29:19 +0000760 return false;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000761 if (Kind == k_PostIndexRegister)
Jim Grosbach5b96b802011-08-10 20:29:19 +0000762 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
763 // Immediate offset in range [-255, 255].
764 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
765 if (!CE) return false;
766 int64_t Val = CE->getValue();
Jim Grosbach1d9d5e92011-08-10 21:56:18 +0000767 // Special case, #-0 is INT32_MIN.
768 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000769 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000770 bool isAddrMode5() const {
Jim Grosbachfb2f1d62011-11-01 01:24:45 +0000771 // If we have an immediate that's not a constant, treat it as a label
772 // reference needing a fixup. If it is a constant, it's something else
773 // and we reject it.
774 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
775 return true;
Jim Grosbacha95ec992011-10-11 17:29:55 +0000776 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000777 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000778 if (Memory.OffsetRegNum) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000779 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbach871dff72011-10-11 15:59:20 +0000780 if (!Memory.OffsetImm) return true;
781 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson967674d2011-08-29 19:36:44 +0000782 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbachfb2f1d62011-11-01 01:24:45 +0000783 Val == INT32_MIN;
Bill Wendling8d2aa032010-11-08 23:49:57 +0000784 }
Jim Grosbach05541f42011-09-19 22:21:13 +0000785 bool isMemTBB() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000786 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000787 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach05541f42011-09-19 22:21:13 +0000788 return false;
789 return true;
790 }
791 bool isMemTBH() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000792 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000793 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
794 Memory.Alignment != 0 )
Jim Grosbach05541f42011-09-19 22:21:13 +0000795 return false;
796 return true;
797 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000798 bool isMemRegOffset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000799 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendling092a7bd2010-12-14 03:36:38 +0000800 return false;
Daniel Dunbar7ed45592011-01-18 05:34:11 +0000801 return true;
Bill Wendling092a7bd2010-12-14 03:36:38 +0000802 }
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000803 bool isT2MemRegOffset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000804 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
805 Memory.Alignment != 0)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000806 return false;
807 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbach871dff72011-10-11 15:59:20 +0000808 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000809 return true;
Jim Grosbach871dff72011-10-11 15:59:20 +0000810 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000811 return false;
812 return true;
813 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000814 bool isMemThumbRR() const {
815 // Thumb reg+reg addressing is simple. Just two registers, a base and
816 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbach871dff72011-10-11 15:59:20 +0000817 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000818 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendling811c9362010-11-30 07:44:32 +0000819 return false;
Jim Grosbach871dff72011-10-11 15:59:20 +0000820 return isARMLowRegister(Memory.BaseRegNum) &&
821 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach3fe94e32011-08-19 17:55:24 +0000822 }
823 bool isMemThumbRIs4() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000824 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000825 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach3fe94e32011-08-19 17:55:24 +0000826 return false;
827 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbach871dff72011-10-11 15:59:20 +0000828 if (!Memory.OffsetImm) return true;
829 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach23983d62011-08-19 18:13:48 +0000830 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
831 }
Jim Grosbach26d35872011-08-19 18:55:51 +0000832 bool isMemThumbRIs2() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000833 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000834 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach26d35872011-08-19 18:55:51 +0000835 return false;
836 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbach871dff72011-10-11 15:59:20 +0000837 if (!Memory.OffsetImm) return true;
838 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach26d35872011-08-19 18:55:51 +0000839 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
840 }
Jim Grosbacha32c7532011-08-19 18:49:59 +0000841 bool isMemThumbRIs1() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000842 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000843 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbacha32c7532011-08-19 18:49:59 +0000844 return false;
845 // Immediate offset in range [0, 31].
Jim Grosbach871dff72011-10-11 15:59:20 +0000846 if (!Memory.OffsetImm) return true;
847 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha32c7532011-08-19 18:49:59 +0000848 return Val >= 0 && Val <= 31;
849 }
Jim Grosbach23983d62011-08-19 18:13:48 +0000850 bool isMemThumbSPI() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000851 if (!isMemory() || Memory.OffsetRegNum != 0 ||
852 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbach23983d62011-08-19 18:13:48 +0000853 return false;
854 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +0000855 if (!Memory.OffsetImm) return true;
856 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach23983d62011-08-19 18:13:48 +0000857 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendling811c9362010-11-30 07:44:32 +0000858 }
Jim Grosbach7db8d692011-09-08 22:07:06 +0000859 bool isMemImm8s4Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000860 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7db8d692011-09-08 22:07:06 +0000861 return false;
862 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +0000863 if (!Memory.OffsetImm) return true;
864 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7db8d692011-09-08 22:07:06 +0000865 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
866 }
Jim Grosbacha05627e2011-09-09 18:37:27 +0000867 bool isMemImm0_1020s4Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000868 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha05627e2011-09-09 18:37:27 +0000869 return false;
870 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +0000871 if (!Memory.OffsetImm) return true;
872 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha05627e2011-09-09 18:37:27 +0000873 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
874 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000875 bool isMemImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000876 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachd3595712011-08-03 23:50:40 +0000877 return false;
878 // Immediate offset in range [-255, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +0000879 if (!Memory.OffsetImm) return true;
880 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson49168402011-09-23 22:25:02 +0000881 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbachd3595712011-08-03 23:50:40 +0000882 }
Jim Grosbach2392c532011-09-07 23:39:14 +0000883 bool isMemPosImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000884 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach2392c532011-09-07 23:39:14 +0000885 return false;
886 // Immediate offset in range [0, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +0000887 if (!Memory.OffsetImm) return true;
888 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2392c532011-09-07 23:39:14 +0000889 return Val >= 0 && Val < 256;
890 }
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +0000891 bool isMemNegImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000892 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +0000893 return false;
894 // Immediate offset in range [-255, -1].
Jim Grosbach871dff72011-10-11 15:59:20 +0000895 if (!Memory.OffsetImm) return true;
896 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +0000897 return Val > -256 && Val < 0;
898 }
899 bool isMemUImm12Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000900 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +0000901 return false;
902 // Immediate offset in range [0, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +0000903 if (!Memory.OffsetImm) return true;
904 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +0000905 return (Val >= 0 && Val < 4096);
906 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000907 bool isMemImm12Offset() const {
Jim Grosbach95466ce2011-08-08 20:59:31 +0000908 // If we have an immediate that's not a constant, treat it as a label
909 // reference needing a fixup. If it is a constant, it's something else
910 // and we reject it.
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000911 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach95466ce2011-08-08 20:59:31 +0000912 return true;
913
Jim Grosbacha95ec992011-10-11 17:29:55 +0000914 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachd3595712011-08-03 23:50:40 +0000915 return false;
916 // Immediate offset in range [-4095, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +0000917 if (!Memory.OffsetImm) return true;
918 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson967674d2011-08-29 19:36:44 +0000919 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbachd3595712011-08-03 23:50:40 +0000920 }
921 bool isPostIdxImm8() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000922 if (Kind != k_Immediate)
Jim Grosbachd3595712011-08-03 23:50:40 +0000923 return false;
924 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
925 if (!CE) return false;
926 int64_t Val = CE->getValue();
Owen Andersonf02d98d2011-08-29 17:17:09 +0000927 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbachd3595712011-08-03 23:50:40 +0000928 }
Jim Grosbach93981412011-10-11 21:55:36 +0000929 bool isPostIdxImm8s4() const {
930 if (Kind != k_Immediate)
931 return false;
932 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
933 if (!CE) return false;
934 int64_t Val = CE->getValue();
935 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
936 (Val == INT32_MIN);
937 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000938
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000939 bool isMSRMask() const { return Kind == k_MSRMask; }
940 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +0000941
Jim Grosbach741cd732011-10-17 22:26:03 +0000942 // NEON operands.
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000943 bool isVecListOneD() const {
944 if (Kind != k_VectorList) return false;
945 return VectorList.Count == 1;
946 }
947
Jim Grosbach2f2e3c42011-10-21 18:54:25 +0000948 bool isVecListTwoD() const {
949 if (Kind != k_VectorList) return false;
950 return VectorList.Count == 2;
951 }
952
Jim Grosbachc4360fe2011-10-21 20:02:19 +0000953 bool isVecListThreeD() const {
954 if (Kind != k_VectorList) return false;
955 return VectorList.Count == 3;
956 }
957
Jim Grosbach846bcff2011-10-21 20:35:01 +0000958 bool isVecListFourD() const {
959 if (Kind != k_VectorList) return false;
960 return VectorList.Count == 4;
961 }
962
Jim Grosbach118b38c2011-10-21 22:21:10 +0000963 bool isVecListTwoQ() const {
964 if (Kind != k_VectorList) return false;
965 //FIXME: We haven't taught the parser to handle by-two register lists
966 // yet, so don't pretend to know one.
967 return VectorList.Count == 2 && false;
968 }
969
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000970 bool isVectorIndex8() const {
971 if (Kind != k_VectorIndex) return false;
972 return VectorIndex.Val < 8;
973 }
974 bool isVectorIndex16() const {
975 if (Kind != k_VectorIndex) return false;
976 return VectorIndex.Val < 4;
977 }
978 bool isVectorIndex32() const {
979 if (Kind != k_VectorIndex) return false;
980 return VectorIndex.Val < 2;
981 }
982
Jim Grosbach741cd732011-10-17 22:26:03 +0000983 bool isNEONi8splat() 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 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
991 // value.
Jim Grosbach741cd732011-10-17 22:26:03 +0000992 return Value >= 0 && Value < 256;
993 }
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000994
Jim Grosbachcda32ae2011-10-17 23:09:09 +0000995 bool isNEONi16splat() const {
996 if (Kind != k_Immediate)
997 return false;
998 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
999 // Must be a constant.
1000 if (!CE) return false;
1001 int64_t Value = CE->getValue();
1002 // i16 value in the range [0,255] or [0x0100, 0xff00]
1003 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1004 }
1005
Jim Grosbach8211c052011-10-18 00:22:00 +00001006 bool isNEONi32splat() const {
1007 if (Kind != k_Immediate)
1008 return false;
1009 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1010 // Must be a constant.
1011 if (!CE) return false;
1012 int64_t Value = CE->getValue();
1013 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1014 return (Value >= 0 && Value < 256) ||
1015 (Value >= 0x0100 && Value <= 0xff00) ||
1016 (Value >= 0x010000 && Value <= 0xff0000) ||
1017 (Value >= 0x01000000 && Value <= 0xff000000);
1018 }
1019
1020 bool isNEONi32vmov() const {
1021 if (Kind != k_Immediate)
1022 return false;
1023 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1024 // Must be a constant.
1025 if (!CE) return false;
1026 int64_t Value = CE->getValue();
1027 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1028 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1029 return (Value >= 0 && Value < 256) ||
1030 (Value >= 0x0100 && Value <= 0xff00) ||
1031 (Value >= 0x010000 && Value <= 0xff0000) ||
1032 (Value >= 0x01000000 && Value <= 0xff000000) ||
1033 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1034 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1035 }
1036
Jim Grosbache4454e02011-10-18 16:18:11 +00001037 bool isNEONi64splat() const {
1038 if (Kind != k_Immediate)
1039 return false;
1040 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1041 // Must be a constant.
1042 if (!CE) return false;
1043 uint64_t Value = CE->getValue();
1044 // i64 value with each byte being either 0 or 0xff.
1045 for (unsigned i = 0; i < 8; ++i)
1046 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1047 return true;
1048 }
1049
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001050 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner5d6f6a02010-10-29 00:27:31 +00001051 // Add as immediates when possible. Null MCExpr = 0.
1052 if (Expr == 0)
1053 Inst.addOperand(MCOperand::CreateImm(0));
1054 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001055 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1056 else
1057 Inst.addOperand(MCOperand::CreateExpr(Expr));
1058 }
1059
Daniel Dunbard8042b72010-08-11 06:36:53 +00001060 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001061 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbard8042b72010-08-11 06:36:53 +00001062 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach968c9272010-12-06 18:30:57 +00001063 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1064 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbard8042b72010-08-11 06:36:53 +00001065 }
1066
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001067 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1068 assert(N == 1 && "Invalid number of operands!");
1069 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1070 }
1071
Jim Grosbach48399582011-10-12 17:34:41 +00001072 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1073 assert(N == 1 && "Invalid number of operands!");
1074 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1075 }
1076
1077 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1078 assert(N == 1 && "Invalid number of operands!");
1079 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1080 }
1081
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001082 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1083 assert(N == 1 && "Invalid number of operands!");
1084 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1085 }
1086
1087 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1088 assert(N == 1 && "Invalid number of operands!");
1089 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1090 }
1091
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001092 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1093 assert(N == 1 && "Invalid number of operands!");
1094 Inst.addOperand(MCOperand::CreateReg(getReg()));
1095 }
1096
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001097 void addRegOperands(MCInst &Inst, unsigned N) const {
1098 assert(N == 1 && "Invalid number of operands!");
1099 Inst.addOperand(MCOperand::CreateReg(getReg()));
1100 }
1101
Jim Grosbachac798e12011-07-25 20:49:51 +00001102 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001103 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001104 assert(isRegShiftedReg() &&
1105 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachac798e12011-07-25 20:49:51 +00001106 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1107 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001108 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachac798e12011-07-25 20:49:51 +00001109 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001110 }
1111
Jim Grosbachac798e12011-07-25 20:49:51 +00001112 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson04912702011-07-21 23:38:37 +00001113 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001114 assert(isRegShiftedImm() &&
1115 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachac798e12011-07-25 20:49:51 +00001116 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Andersonb595ed02011-07-21 18:54:16 +00001117 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachac798e12011-07-25 20:49:51 +00001118 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Andersonb595ed02011-07-21 18:54:16 +00001119 }
1120
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001121 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001122 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001123 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1124 ShifterImm.Imm));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001125 }
1126
Bill Wendling8d2aa032010-11-08 23:49:57 +00001127 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling2cae3272010-11-09 22:44:22 +00001128 assert(N == 1 && "Invalid number of operands!");
Bill Wendlingbed94652010-11-09 23:28:44 +00001129 const SmallVectorImpl<unsigned> &RegList = getRegList();
1130 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00001131 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1132 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling8d2aa032010-11-08 23:49:57 +00001133 }
1134
Bill Wendling9898ac92010-11-17 04:32:08 +00001135 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1136 addRegListOperands(Inst, N);
1137 }
1138
1139 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1140 addRegListOperands(Inst, N);
1141 }
1142
Jim Grosbach833b9d32011-07-27 20:15:40 +00001143 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1144 assert(N == 1 && "Invalid number of operands!");
1145 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1146 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1147 }
1148
Jim Grosbach864b6092011-07-28 21:34:26 +00001149 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1150 assert(N == 1 && "Invalid number of operands!");
1151 // Munge the lsb/width into a bitfield mask.
1152 unsigned lsb = Bitfield.LSB;
1153 unsigned width = Bitfield.Width;
1154 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1155 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1156 (32 - (lsb + width)));
1157 Inst.addOperand(MCOperand::CreateImm(Mask));
1158 }
1159
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001160 void addImmOperands(MCInst &Inst, unsigned N) const {
1161 assert(N == 1 && "Invalid number of operands!");
1162 addExpr(Inst, getImm());
1163 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00001164
Jim Grosbache7fbce72011-10-03 23:38:36 +00001165 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1166 assert(N == 1 && "Invalid number of operands!");
1167 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1168 }
1169
Jim Grosbach7db8d692011-09-08 22:07:06 +00001170 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1171 assert(N == 1 && "Invalid number of operands!");
1172 // FIXME: We really want to scale the value here, but the LDRD/STRD
1173 // instruction don't encode operands that way yet.
1174 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1175 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1176 }
1177
Jim Grosbach0a0b3072011-08-24 21:22:15 +00001178 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1179 assert(N == 1 && "Invalid number of operands!");
1180 // The immediate is scaled by four in the encoding and is stored
1181 // in the MCInst as such. Lop off the low two bits here.
1182 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1183 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1184 }
1185
1186 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1187 assert(N == 1 && "Invalid number of operands!");
1188 // The immediate is scaled by four in the encoding and is stored
1189 // in the MCInst as such. Lop off the low two bits here.
1190 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1191 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1192 }
1193
Jim Grosbach475c6db2011-07-25 23:09:14 +00001194 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1195 assert(N == 1 && "Invalid number of operands!");
1196 // The constant encodes as the immediate-1, and we store in the instruction
1197 // the bits as encoded, so subtract off one here.
1198 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1199 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1200 }
1201
Jim Grosbach801e0a32011-07-22 23:16:18 +00001202 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1203 assert(N == 1 && "Invalid number of operands!");
1204 // The constant encodes as the immediate-1, and we store in the instruction
1205 // the bits as encoded, so subtract off one here.
1206 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1207 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1208 }
1209
Jim Grosbach46dd4132011-08-17 21:51:27 +00001210 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1211 assert(N == 1 && "Invalid number of operands!");
1212 // The constant encodes as the immediate, except for 32, which encodes as
1213 // zero.
1214 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1215 unsigned Imm = CE->getValue();
1216 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1217 }
1218
Jim Grosbach27c1e252011-07-21 17:23:04 +00001219 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1220 assert(N == 1 && "Invalid number of operands!");
1221 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1222 // the instruction as well.
1223 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1224 int Val = CE->getValue();
1225 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1226 }
1227
Jim Grosbachb009a872011-10-28 22:36:30 +00001228 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1229 assert(N == 1 && "Invalid number of operands!");
1230 // The operand is actually a t2_so_imm, but we have its bitwise
1231 // negation in the assembly source, so twiddle it here.
1232 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1233 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1234 }
1235
Jim Grosbach3d785ed2011-10-28 22:50:54 +00001236 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1237 assert(N == 1 && "Invalid number of operands!");
1238 // The operand is actually a so_imm, but we have its bitwise
1239 // negation in the assembly source, so twiddle it here.
1240 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1241 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1242 }
1243
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001244 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1245 assert(N == 1 && "Invalid number of operands!");
1246 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1247 }
1248
Jim Grosbachd3595712011-08-03 23:50:40 +00001249 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1250 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001251 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopesf170f8b2011-03-24 21:04:58 +00001252 }
1253
Jim Grosbacha95ec992011-10-11 17:29:55 +00001254 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1255 assert(N == 2 && "Invalid number of operands!");
1256 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1257 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1258 }
1259
Jim Grosbachd3595712011-08-03 23:50:40 +00001260 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1261 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001262 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1263 if (!Memory.OffsetRegNum) {
Jim Grosbachd3595712011-08-03 23:50:40 +00001264 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1265 // Special case for #-0
1266 if (Val == INT32_MIN) Val = 0;
1267 if (Val < 0) Val = -Val;
1268 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1269 } else {
1270 // For register offset, we encode the shift type and negation flag
1271 // here.
Jim Grosbach871dff72011-10-11 15:59:20 +00001272 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1273 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001274 }
Jim Grosbach871dff72011-10-11 15:59:20 +00001275 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1276 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001277 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001278 }
1279
Jim Grosbachcd17c122011-08-04 23:01:30 +00001280 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1281 assert(N == 2 && "Invalid number of operands!");
1282 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1283 assert(CE && "non-constant AM2OffsetImm operand!");
1284 int32_t Val = CE->getValue();
1285 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1286 // Special case for #-0
1287 if (Val == INT32_MIN) Val = 0;
1288 if (Val < 0) Val = -Val;
1289 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1290 Inst.addOperand(MCOperand::CreateReg(0));
1291 Inst.addOperand(MCOperand::CreateImm(Val));
1292 }
1293
Jim Grosbach5b96b802011-08-10 20:29:19 +00001294 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1295 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001296 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1297 if (!Memory.OffsetRegNum) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00001298 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1299 // Special case for #-0
1300 if (Val == INT32_MIN) Val = 0;
1301 if (Val < 0) Val = -Val;
1302 Val = ARM_AM::getAM3Opc(AddSub, Val);
1303 } else {
1304 // For register offset, we encode the shift type and negation flag
1305 // here.
Jim Grosbach871dff72011-10-11 15:59:20 +00001306 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach5b96b802011-08-10 20:29:19 +00001307 }
Jim Grosbach871dff72011-10-11 15:59:20 +00001308 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1309 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach5b96b802011-08-10 20:29:19 +00001310 Inst.addOperand(MCOperand::CreateImm(Val));
1311 }
1312
1313 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1314 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001315 if (Kind == k_PostIndexRegister) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00001316 int32_t Val =
1317 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1318 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1319 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001320 return;
Jim Grosbach5b96b802011-08-10 20:29:19 +00001321 }
1322
1323 // Constant offset.
1324 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
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;
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001330 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach5b96b802011-08-10 20:29:19 +00001331 Inst.addOperand(MCOperand::CreateReg(0));
1332 Inst.addOperand(MCOperand::CreateImm(Val));
1333 }
1334
Jim Grosbachd3595712011-08-03 23:50:40 +00001335 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1336 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachfb2f1d62011-11-01 01:24:45 +00001337 // If we have an immediate that's not a constant, treat it as a label
1338 // reference needing a fixup. If it is a constant, it's something else
1339 // and we reject it.
1340 if (isImm()) {
1341 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1342 Inst.addOperand(MCOperand::CreateImm(0));
1343 return;
1344 }
1345
Jim Grosbachd3595712011-08-03 23:50:40 +00001346 // The lower two bits are always zero and as such are not encoded.
Jim Grosbach871dff72011-10-11 15:59:20 +00001347 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00001348 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1349 // Special case for #-0
1350 if (Val == INT32_MIN) Val = 0;
1351 if (Val < 0) Val = -Val;
1352 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbach871dff72011-10-11 15:59:20 +00001353 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001354 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00001355 }
1356
Jim Grosbach7db8d692011-09-08 22:07:06 +00001357 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1358 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001359 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1360 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7db8d692011-09-08 22:07:06 +00001361 Inst.addOperand(MCOperand::CreateImm(Val));
1362 }
1363
Jim Grosbacha05627e2011-09-09 18:37:27 +00001364 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1365 assert(N == 2 && "Invalid number of operands!");
1366 // The lower two bits are always zero and as such are not encoded.
Jim Grosbach871dff72011-10-11 15:59:20 +00001367 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1368 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha05627e2011-09-09 18:37:27 +00001369 Inst.addOperand(MCOperand::CreateImm(Val));
1370 }
1371
Jim Grosbachd3595712011-08-03 23:50:40 +00001372 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1373 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001374 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1375 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001376 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner5d6f6a02010-10-29 00:27:31 +00001377 }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001378
Jim Grosbach2392c532011-09-07 23:39:14 +00001379 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1380 addMemImm8OffsetOperands(Inst, N);
1381 }
1382
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001383 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach2392c532011-09-07 23:39:14 +00001384 addMemImm8OffsetOperands(Inst, N);
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001385 }
1386
1387 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1388 assert(N == 2 && "Invalid number of operands!");
1389 // If this is an immediate, it's a label reference.
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001390 if (Kind == k_Immediate) {
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001391 addExpr(Inst, getImm());
1392 Inst.addOperand(MCOperand::CreateImm(0));
1393 return;
1394 }
1395
1396 // Otherwise, it's a normal memory reg+offset.
Jim Grosbach871dff72011-10-11 15:59:20 +00001397 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1398 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001399 Inst.addOperand(MCOperand::CreateImm(Val));
1400 }
1401
Jim Grosbachd3595712011-08-03 23:50:40 +00001402 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1403 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach95466ce2011-08-08 20:59:31 +00001404 // If this is an immediate, it's a label reference.
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001405 if (Kind == k_Immediate) {
Jim Grosbach95466ce2011-08-08 20:59:31 +00001406 addExpr(Inst, getImm());
1407 Inst.addOperand(MCOperand::CreateImm(0));
1408 return;
1409 }
1410
1411 // Otherwise, it's a normal memory reg+offset.
Jim Grosbach871dff72011-10-11 15:59:20 +00001412 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1413 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001414 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendling092a7bd2010-12-14 03:36:38 +00001415 }
Bill Wendling811c9362010-11-30 07:44:32 +00001416
Jim Grosbach05541f42011-09-19 22:21:13 +00001417 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1418 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001419 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1420 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach05541f42011-09-19 22:21:13 +00001421 }
1422
1423 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1424 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001425 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1426 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach05541f42011-09-19 22:21:13 +00001427 }
1428
Jim Grosbachd3595712011-08-03 23:50:40 +00001429 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1430 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001431 unsigned Val =
1432 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1433 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbach871dff72011-10-11 15:59:20 +00001434 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1435 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001436 Inst.addOperand(MCOperand::CreateImm(Val));
1437 }
1438
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001439 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1440 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001441 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1442 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1443 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001444 }
1445
Jim Grosbachd3595712011-08-03 23:50:40 +00001446 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1447 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001448 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1449 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001450 }
1451
Jim Grosbach3fe94e32011-08-19 17:55:24 +00001452 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1453 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001454 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1455 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach3fe94e32011-08-19 17:55:24 +00001456 Inst.addOperand(MCOperand::CreateImm(Val));
1457 }
1458
Jim Grosbach26d35872011-08-19 18:55:51 +00001459 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1460 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001461 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1462 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach26d35872011-08-19 18:55:51 +00001463 Inst.addOperand(MCOperand::CreateImm(Val));
1464 }
1465
Jim Grosbacha32c7532011-08-19 18:49:59 +00001466 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1467 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001468 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1469 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha32c7532011-08-19 18:49:59 +00001470 Inst.addOperand(MCOperand::CreateImm(Val));
1471 }
1472
Jim Grosbach23983d62011-08-19 18:13:48 +00001473 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1474 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001475 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1476 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach23983d62011-08-19 18:13:48 +00001477 Inst.addOperand(MCOperand::CreateImm(Val));
1478 }
1479
Jim Grosbachd3595712011-08-03 23:50:40 +00001480 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1481 assert(N == 1 && "Invalid number of operands!");
1482 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1483 assert(CE && "non-constant post-idx-imm8 operand!");
1484 int Imm = CE->getValue();
1485 bool isAdd = Imm >= 0;
Owen Andersonf02d98d2011-08-29 17:17:09 +00001486 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00001487 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1488 Inst.addOperand(MCOperand::CreateImm(Imm));
1489 }
1490
Jim Grosbach93981412011-10-11 21:55:36 +00001491 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1492 assert(N == 1 && "Invalid number of operands!");
1493 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1494 assert(CE && "non-constant post-idx-imm8s4 operand!");
1495 int Imm = CE->getValue();
1496 bool isAdd = Imm >= 0;
1497 if (Imm == INT32_MIN) Imm = 0;
1498 // Immediate is scaled by 4.
1499 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1500 Inst.addOperand(MCOperand::CreateImm(Imm));
1501 }
1502
Jim Grosbachd3595712011-08-03 23:50:40 +00001503 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1504 assert(N == 2 && "Invalid number of operands!");
1505 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachc320c852011-08-05 21:28:30 +00001506 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1507 }
1508
1509 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1510 assert(N == 2 && "Invalid number of operands!");
1511 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1512 // The sign, shift type, and shift amount are encoded in a single operand
1513 // using the AM2 encoding helpers.
1514 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1515 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1516 PostIdxReg.ShiftTy);
1517 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendling811c9362010-11-30 07:44:32 +00001518 }
1519
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001520 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1521 assert(N == 1 && "Invalid number of operands!");
1522 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1523 }
1524
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001525 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1526 assert(N == 1 && "Invalid number of operands!");
1527 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1528 }
1529
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001530 void addVecListOneDOperands(MCInst &Inst, unsigned N) const {
1531 assert(N == 1 && "Invalid number of operands!");
1532 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1533 }
1534
Jim Grosbach2f2e3c42011-10-21 18:54:25 +00001535 void addVecListTwoDOperands(MCInst &Inst, unsigned N) const {
1536 assert(N == 1 && "Invalid number of operands!");
1537 // Only the first register actually goes on the instruction. The rest
1538 // are implied by the opcode.
1539 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1540 }
1541
Jim Grosbachc4360fe2011-10-21 20:02:19 +00001542 void addVecListThreeDOperands(MCInst &Inst, unsigned N) const {
1543 assert(N == 1 && "Invalid number of operands!");
1544 // Only the first register actually goes on the instruction. The rest
1545 // are implied by the opcode.
1546 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1547 }
1548
Jim Grosbach846bcff2011-10-21 20:35:01 +00001549 void addVecListFourDOperands(MCInst &Inst, unsigned N) const {
1550 assert(N == 1 && "Invalid number of operands!");
1551 // Only the first register actually goes on the instruction. The rest
1552 // are implied by the opcode.
1553 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1554 }
1555
Jim Grosbach118b38c2011-10-21 22:21:10 +00001556 void addVecListTwoQOperands(MCInst &Inst, unsigned N) const {
1557 assert(N == 1 && "Invalid number of operands!");
1558 // Only the first register actually goes on the instruction. The rest
1559 // are implied by the opcode.
1560 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1561 }
1562
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001563 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1564 assert(N == 1 && "Invalid number of operands!");
1565 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1566 }
1567
1568 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1569 assert(N == 1 && "Invalid number of operands!");
1570 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1571 }
1572
1573 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1574 assert(N == 1 && "Invalid number of operands!");
1575 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1576 }
1577
Jim Grosbach741cd732011-10-17 22:26:03 +00001578 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1579 assert(N == 1 && "Invalid number of operands!");
1580 // The immediate encodes the type of constant as well as the value.
1581 // Mask in that this is an i8 splat.
1582 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1583 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1584 }
1585
Jim Grosbachcda32ae2011-10-17 23:09:09 +00001586 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1587 assert(N == 1 && "Invalid number of operands!");
1588 // The immediate encodes the type of constant as well as the value.
1589 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1590 unsigned Value = CE->getValue();
1591 if (Value >= 256)
1592 Value = (Value >> 8) | 0xa00;
1593 else
1594 Value |= 0x800;
1595 Inst.addOperand(MCOperand::CreateImm(Value));
1596 }
1597
Jim Grosbach8211c052011-10-18 00:22:00 +00001598 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1599 assert(N == 1 && "Invalid number of operands!");
1600 // The immediate encodes the type of constant as well as the value.
1601 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1602 unsigned Value = CE->getValue();
1603 if (Value >= 256 && Value <= 0xff00)
1604 Value = (Value >> 8) | 0x200;
1605 else if (Value > 0xffff && Value <= 0xff0000)
1606 Value = (Value >> 16) | 0x400;
1607 else if (Value > 0xffffff)
1608 Value = (Value >> 24) | 0x600;
1609 Inst.addOperand(MCOperand::CreateImm(Value));
1610 }
1611
1612 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1613 assert(N == 1 && "Invalid number of operands!");
1614 // The immediate encodes the type of constant as well as the value.
1615 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1616 unsigned Value = CE->getValue();
1617 if (Value >= 256 && Value <= 0xffff)
1618 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1619 else if (Value > 0xffff && Value <= 0xffffff)
1620 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1621 else if (Value > 0xffffff)
1622 Value = (Value >> 24) | 0x600;
1623 Inst.addOperand(MCOperand::CreateImm(Value));
1624 }
1625
Jim Grosbache4454e02011-10-18 16:18:11 +00001626 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1627 assert(N == 1 && "Invalid number of operands!");
1628 // The immediate encodes the type of constant as well as the value.
1629 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1630 uint64_t Value = CE->getValue();
1631 unsigned Imm = 0;
1632 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1633 Imm |= (Value & 1) << i;
1634 }
1635 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1636 }
1637
Jim Grosbach602aa902011-07-13 15:34:57 +00001638 virtual void print(raw_ostream &OS) const;
Daniel Dunbarebace222010-08-11 06:37:04 +00001639
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001640 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001641 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001642 Op->ITMask.Mask = Mask;
1643 Op->StartLoc = S;
1644 Op->EndLoc = S;
1645 return Op;
1646 }
1647
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001648 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001649 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001650 Op->CC.Val = CC;
1651 Op->StartLoc = S;
1652 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001653 return Op;
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001654 }
1655
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001656 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001657 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001658 Op->Cop.Val = CopVal;
1659 Op->StartLoc = S;
1660 Op->EndLoc = S;
1661 return Op;
1662 }
1663
1664 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001665 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001666 Op->Cop.Val = CopVal;
1667 Op->StartLoc = S;
1668 Op->EndLoc = S;
1669 return Op;
1670 }
1671
Jim Grosbach48399582011-10-12 17:34:41 +00001672 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1673 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1674 Op->Cop.Val = Val;
1675 Op->StartLoc = S;
1676 Op->EndLoc = E;
1677 return Op;
1678 }
1679
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001680 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001681 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001682 Op->Reg.RegNum = RegNum;
1683 Op->StartLoc = S;
1684 Op->EndLoc = S;
1685 return Op;
1686 }
1687
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001688 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001689 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001690 Op->Tok.Data = Str.data();
1691 Op->Tok.Length = Str.size();
1692 Op->StartLoc = S;
1693 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001694 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001695 }
1696
Bill Wendling2063b842010-11-18 23:43:05 +00001697 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001698 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001699 Op->Reg.RegNum = RegNum;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001700 Op->StartLoc = S;
1701 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001702 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001703 }
1704
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001705 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1706 unsigned SrcReg,
1707 unsigned ShiftReg,
1708 unsigned ShiftImm,
1709 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001710 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachac798e12011-07-25 20:49:51 +00001711 Op->RegShiftedReg.ShiftTy = ShTy;
1712 Op->RegShiftedReg.SrcReg = SrcReg;
1713 Op->RegShiftedReg.ShiftReg = ShiftReg;
1714 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001715 Op->StartLoc = S;
1716 Op->EndLoc = E;
1717 return Op;
1718 }
1719
Owen Andersonb595ed02011-07-21 18:54:16 +00001720 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1721 unsigned SrcReg,
1722 unsigned ShiftImm,
1723 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001724 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachac798e12011-07-25 20:49:51 +00001725 Op->RegShiftedImm.ShiftTy = ShTy;
1726 Op->RegShiftedImm.SrcReg = SrcReg;
1727 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Andersonb595ed02011-07-21 18:54:16 +00001728 Op->StartLoc = S;
1729 Op->EndLoc = E;
1730 return Op;
1731 }
1732
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001733 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001734 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001735 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001736 Op->ShifterImm.isASR = isASR;
1737 Op->ShifterImm.Imm = Imm;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001738 Op->StartLoc = S;
1739 Op->EndLoc = E;
1740 return Op;
1741 }
1742
Jim Grosbach833b9d32011-07-27 20:15:40 +00001743 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001744 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach833b9d32011-07-27 20:15:40 +00001745 Op->RotImm.Imm = Imm;
1746 Op->StartLoc = S;
1747 Op->EndLoc = E;
1748 return Op;
1749 }
1750
Jim Grosbach864b6092011-07-28 21:34:26 +00001751 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1752 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001753 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach864b6092011-07-28 21:34:26 +00001754 Op->Bitfield.LSB = LSB;
1755 Op->Bitfield.Width = Width;
1756 Op->StartLoc = S;
1757 Op->EndLoc = E;
1758 return Op;
1759 }
1760
Bill Wendling2cae3272010-11-09 22:44:22 +00001761 static ARMOperand *
Bill Wendlingbed94652010-11-09 23:28:44 +00001762 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00001763 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001764 KindTy Kind = k_RegisterList;
Bill Wendling9898ac92010-11-17 04:32:08 +00001765
Jim Grosbach75461af2011-09-13 22:56:44 +00001766 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001767 Kind = k_DPRRegisterList;
Jim Grosbach75461af2011-09-13 22:56:44 +00001768 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng9eec7642011-07-25 21:32:49 +00001769 contains(Regs.front().first))
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001770 Kind = k_SPRRegisterList;
Bill Wendling9898ac92010-11-17 04:32:08 +00001771
1772 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendlingbed94652010-11-09 23:28:44 +00001773 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00001774 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling0ab0f672010-11-18 21:50:54 +00001775 Op->Registers.push_back(I->first);
Bill Wendling20b5ea982010-11-19 00:38:19 +00001776 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00001777 Op->StartLoc = StartLoc;
1778 Op->EndLoc = EndLoc;
Bill Wendling7cef4472010-11-06 19:56:04 +00001779 return Op;
1780 }
1781
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001782 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
1783 SMLoc S, SMLoc E) {
1784 ARMOperand *Op = new ARMOperand(k_VectorList);
1785 Op->VectorList.RegNum = RegNum;
1786 Op->VectorList.Count = Count;
1787 Op->StartLoc = S;
1788 Op->EndLoc = E;
1789 return Op;
1790 }
1791
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001792 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
1793 MCContext &Ctx) {
1794 ARMOperand *Op = new ARMOperand(k_VectorIndex);
1795 Op->VectorIndex.Val = Idx;
1796 Op->StartLoc = S;
1797 Op->EndLoc = E;
1798 return Op;
1799 }
1800
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001801 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001802 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001803 Op->Imm.Val = Val;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001804 Op->StartLoc = S;
1805 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001806 return Op;
Kevin Enderbyf5079942009-10-13 22:19:02 +00001807 }
1808
Jim Grosbache7fbce72011-10-03 23:38:36 +00001809 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001810 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbache7fbce72011-10-03 23:38:36 +00001811 Op->FPImm.Val = Val;
1812 Op->StartLoc = S;
1813 Op->EndLoc = S;
1814 return Op;
1815 }
1816
Jim Grosbachd3595712011-08-03 23:50:40 +00001817 static ARMOperand *CreateMem(unsigned BaseRegNum,
1818 const MCConstantExpr *OffsetImm,
1819 unsigned OffsetRegNum,
1820 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00001821 unsigned ShiftImm,
Jim Grosbacha95ec992011-10-11 17:29:55 +00001822 unsigned Alignment,
Jim Grosbachd3595712011-08-03 23:50:40 +00001823 bool isNegative,
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001824 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001825 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbach871dff72011-10-11 15:59:20 +00001826 Op->Memory.BaseRegNum = BaseRegNum;
1827 Op->Memory.OffsetImm = OffsetImm;
1828 Op->Memory.OffsetRegNum = OffsetRegNum;
1829 Op->Memory.ShiftType = ShiftType;
1830 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbacha95ec992011-10-11 17:29:55 +00001831 Op->Memory.Alignment = Alignment;
Jim Grosbach871dff72011-10-11 15:59:20 +00001832 Op->Memory.isNegative = isNegative;
Jim Grosbachd3595712011-08-03 23:50:40 +00001833 Op->StartLoc = S;
1834 Op->EndLoc = E;
1835 return Op;
1836 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00001837
Jim Grosbachc320c852011-08-05 21:28:30 +00001838 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
1839 ARM_AM::ShiftOpc ShiftTy,
1840 unsigned ShiftImm,
Jim Grosbachd3595712011-08-03 23:50:40 +00001841 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001842 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbachd3595712011-08-03 23:50:40 +00001843 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachc320c852011-08-05 21:28:30 +00001844 Op->PostIdxReg.isAdd = isAdd;
1845 Op->PostIdxReg.ShiftTy = ShiftTy;
1846 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001847 Op->StartLoc = S;
1848 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001849 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001850 }
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001851
1852 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001853 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001854 Op->MBOpt.Val = Opt;
1855 Op->StartLoc = S;
1856 Op->EndLoc = S;
1857 return Op;
1858 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001859
1860 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001861 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001862 Op->IFlags.Val = IFlags;
1863 Op->StartLoc = S;
1864 Op->EndLoc = S;
1865 return Op;
1866 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001867
1868 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001869 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001870 Op->MMask.Val = MMask;
1871 Op->StartLoc = S;
1872 Op->EndLoc = S;
1873 return Op;
1874 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001875};
1876
1877} // end anonymous namespace.
1878
Jim Grosbach602aa902011-07-13 15:34:57 +00001879void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001880 switch (Kind) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001881 case k_FPImmediate:
Jim Grosbache7fbce72011-10-03 23:38:36 +00001882 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
1883 << ") >";
1884 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001885 case k_CondCode:
Daniel Dunbar2be732a2011-01-10 15:26:21 +00001886 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001887 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001888 case k_CCOut:
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001889 OS << "<ccout " << getReg() << ">";
1890 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001891 case k_ITCondMask: {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00001892 static const char *MaskStr[] = {
1893 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
1894 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
1895 };
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001896 assert((ITMask.Mask & 0xf) == ITMask.Mask);
1897 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
1898 break;
1899 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001900 case k_CoprocNum:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001901 OS << "<coprocessor number: " << getCoproc() << ">";
1902 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001903 case k_CoprocReg:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001904 OS << "<coprocessor register: " << getCoproc() << ">";
1905 break;
Jim Grosbach48399582011-10-12 17:34:41 +00001906 case k_CoprocOption:
1907 OS << "<coprocessor option: " << CoprocOption.Val << ">";
1908 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001909 case k_MSRMask:
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001910 OS << "<mask: " << getMSRMask() << ">";
1911 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001912 case k_Immediate:
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001913 getImm()->print(OS);
1914 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001915 case k_MemBarrierOpt:
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001916 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
1917 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001918 case k_Memory:
Daniel Dunbarbcd8eb02011-01-18 05:55:21 +00001919 OS << "<memory "
Jim Grosbach871dff72011-10-11 15:59:20 +00001920 << " base:" << Memory.BaseRegNum;
Daniel Dunbarbcd8eb02011-01-18 05:55:21 +00001921 OS << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001922 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001923 case k_PostIndexRegister:
Jim Grosbachc320c852011-08-05 21:28:30 +00001924 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
1925 << PostIdxReg.RegNum;
1926 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
1927 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
1928 << PostIdxReg.ShiftImm;
1929 OS << ">";
Jim Grosbachd3595712011-08-03 23:50:40 +00001930 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001931 case k_ProcIFlags: {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001932 OS << "<ARM_PROC::";
1933 unsigned IFlags = getProcIFlags();
1934 for (int i=2; i >= 0; --i)
1935 if (IFlags & (1 << i))
1936 OS << ARM_PROC::IFlagsToString(1 << i);
1937 OS << ">";
1938 break;
1939 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001940 case k_Register:
Bill Wendling2063b842010-11-18 23:43:05 +00001941 OS << "<register " << getReg() << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001942 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001943 case k_ShifterImmediate:
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001944 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
1945 << " #" << ShifterImm.Imm << ">";
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001946 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001947 case k_ShiftedRegister:
Owen Andersonb595ed02011-07-21 18:54:16 +00001948 OS << "<so_reg_reg "
Jim Grosbachac798e12011-07-25 20:49:51 +00001949 << RegShiftedReg.SrcReg
1950 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedReg.ShiftImm))
1951 << ", " << RegShiftedReg.ShiftReg << ", "
1952 << ARM_AM::getSORegOffset(RegShiftedReg.ShiftImm)
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001953 << ">";
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001954 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001955 case k_ShiftedImmediate:
Owen Andersonb595ed02011-07-21 18:54:16 +00001956 OS << "<so_reg_imm "
Jim Grosbachac798e12011-07-25 20:49:51 +00001957 << RegShiftedImm.SrcReg
1958 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedImm.ShiftImm))
1959 << ", " << ARM_AM::getSORegOffset(RegShiftedImm.ShiftImm)
Owen Andersonb595ed02011-07-21 18:54:16 +00001960 << ">";
1961 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001962 case k_RotateImmediate:
Jim Grosbach833b9d32011-07-27 20:15:40 +00001963 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
1964 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001965 case k_BitfieldDescriptor:
Jim Grosbach864b6092011-07-28 21:34:26 +00001966 OS << "<bitfield " << "lsb: " << Bitfield.LSB
1967 << ", width: " << Bitfield.Width << ">";
1968 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001969 case k_RegisterList:
1970 case k_DPRRegisterList:
1971 case k_SPRRegisterList: {
Bill Wendling7cef4472010-11-06 19:56:04 +00001972 OS << "<register_list ";
Bill Wendling7cef4472010-11-06 19:56:04 +00001973
Bill Wendlingbed94652010-11-09 23:28:44 +00001974 const SmallVectorImpl<unsigned> &RegList = getRegList();
1975 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00001976 I = RegList.begin(), E = RegList.end(); I != E; ) {
1977 OS << *I;
1978 if (++I < E) OS << ", ";
Bill Wendling7cef4472010-11-06 19:56:04 +00001979 }
1980
1981 OS << ">";
1982 break;
1983 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001984 case k_VectorList:
1985 OS << "<vector_list " << VectorList.Count << " * "
1986 << VectorList.RegNum << ">";
1987 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001988 case k_Token:
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001989 OS << "'" << getToken() << "'";
1990 break;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001991 case k_VectorIndex:
1992 OS << "<vectorindex " << getVectorIndex() << ">";
1993 break;
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001994 }
1995}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001996
1997/// @name Auto-generated Match Functions
1998/// {
1999
2000static unsigned MatchRegisterName(StringRef Name);
2001
2002/// }
2003
Bob Wilsonfb0bd042011-02-03 21:46:10 +00002004bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2005 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002006 RegNo = tryParseRegister();
Roman Divacky36b1b472011-01-27 17:14:22 +00002007
2008 return (RegNo == (unsigned)-1);
2009}
2010
Kevin Enderby8be42bd2009-10-30 22:55:57 +00002011/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattner44e5981c2010-10-30 04:09:10 +00002012/// and if it is a register name the token is eaten and the register number is
2013/// returned. Otherwise return -1.
2014///
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002015int ARMAsmParser::tryParseRegister() {
Chris Lattner44e5981c2010-10-30 04:09:10 +00002016 const AsmToken &Tok = Parser.getTok();
Jim Grosbachd3595712011-08-03 23:50:40 +00002017 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbach99710a82010-11-01 16:44:21 +00002018
Chris Lattner44e5981c2010-10-30 04:09:10 +00002019 // FIXME: Validate register for the current architecture; we have to do
2020 // validation later, so maybe there is no need for this here.
Benjamin Kramer20baffb2011-11-06 20:37:06 +00002021 std::string lowerCase = Tok.getString().lower();
Owen Andersona098d152011-01-13 22:50:36 +00002022 unsigned RegNum = MatchRegisterName(lowerCase);
2023 if (!RegNum) {
2024 RegNum = StringSwitch<unsigned>(lowerCase)
2025 .Case("r13", ARM::SP)
2026 .Case("r14", ARM::LR)
2027 .Case("r15", ARM::PC)
2028 .Case("ip", ARM::R12)
2029 .Default(0);
2030 }
2031 if (!RegNum) return -1;
Bob Wilsonfb0bd042011-02-03 21:46:10 +00002032
Chris Lattner44e5981c2010-10-30 04:09:10 +00002033 Parser.Lex(); // Eat identifier token.
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002034
Chris Lattner44e5981c2010-10-30 04:09:10 +00002035 return RegNum;
2036}
Jim Grosbach99710a82010-11-01 16:44:21 +00002037
Jim Grosbachbb24c592011-07-13 18:49:30 +00002038// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2039// If a recoverable error occurs, return 1. If an irrecoverable error
2040// occurs, return -1. An irrecoverable error is one where tokens have been
2041// consumed in the process of trying to parse the shifter (i.e., when it is
2042// indeed a shifter operand, but malformed).
Jim Grosbach0d6022d2011-07-26 20:41:24 +00002043int ARMAsmParser::tryParseShiftRegister(
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002044 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2045 SMLoc S = Parser.getTok().getLoc();
2046 const AsmToken &Tok = Parser.getTok();
2047 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2048
Benjamin Kramer20baffb2011-11-06 20:37:06 +00002049 std::string lowerCase = Tok.getString().lower();
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002050 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
2051 .Case("lsl", ARM_AM::lsl)
2052 .Case("lsr", ARM_AM::lsr)
2053 .Case("asr", ARM_AM::asr)
2054 .Case("ror", ARM_AM::ror)
2055 .Case("rrx", ARM_AM::rrx)
2056 .Default(ARM_AM::no_shift);
2057
2058 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbachbb24c592011-07-13 18:49:30 +00002059 return 1;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002060
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002061 Parser.Lex(); // Eat the operator.
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002062
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002063 // The source register for the shift has already been added to the
2064 // operand list, so we need to pop it off and combine it into the shifted
2065 // register operand instead.
Benjamin Kramer1757e7a2011-07-14 18:41:22 +00002066 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002067 if (!PrevOp->isReg())
2068 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2069 int SrcReg = PrevOp->getReg();
2070 int64_t Imm = 0;
2071 int ShiftReg = 0;
2072 if (ShiftTy == ARM_AM::rrx) {
2073 // RRX Doesn't have an explicit shift amount. The encoder expects
2074 // the shift register to be the same as the source register. Seems odd,
2075 // but OK.
2076 ShiftReg = SrcReg;
2077 } else {
2078 // Figure out if this is shifted by a constant or a register (for non-RRX).
2079 if (Parser.getTok().is(AsmToken::Hash)) {
2080 Parser.Lex(); // Eat hash.
2081 SMLoc ImmLoc = Parser.getTok().getLoc();
2082 const MCExpr *ShiftExpr = 0;
Jim Grosbachbb24c592011-07-13 18:49:30 +00002083 if (getParser().ParseExpression(ShiftExpr)) {
2084 Error(ImmLoc, "invalid immediate shift value");
2085 return -1;
2086 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002087 // The expression must be evaluatable as an immediate.
2088 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbachbb24c592011-07-13 18:49:30 +00002089 if (!CE) {
2090 Error(ImmLoc, "invalid immediate shift value");
2091 return -1;
2092 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002093 // Range check the immediate.
2094 // lsl, ror: 0 <= imm <= 31
2095 // lsr, asr: 0 <= imm <= 32
2096 Imm = CE->getValue();
2097 if (Imm < 0 ||
2098 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2099 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbachbb24c592011-07-13 18:49:30 +00002100 Error(ImmLoc, "immediate shift value out of range");
2101 return -1;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002102 }
2103 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002104 ShiftReg = tryParseRegister();
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002105 SMLoc L = Parser.getTok().getLoc();
Jim Grosbachbb24c592011-07-13 18:49:30 +00002106 if (ShiftReg == -1) {
2107 Error (L, "expected immediate or register in shift operand");
2108 return -1;
2109 }
2110 } else {
2111 Error (Parser.getTok().getLoc(),
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002112 "expected immediate or register in shift operand");
Jim Grosbachbb24c592011-07-13 18:49:30 +00002113 return -1;
2114 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002115 }
2116
Owen Andersonb595ed02011-07-21 18:54:16 +00002117 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2118 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachac798e12011-07-25 20:49:51 +00002119 ShiftReg, Imm,
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002120 S, Parser.getTok().getLoc()));
Owen Andersonb595ed02011-07-21 18:54:16 +00002121 else
2122 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2123 S, Parser.getTok().getLoc()));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002124
Jim Grosbachbb24c592011-07-13 18:49:30 +00002125 return 0;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002126}
2127
2128
Bill Wendling2063b842010-11-18 23:43:05 +00002129/// Try to parse a register name. The token must be an Identifier when called.
2130/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2131/// if there is a "writeback". 'true' if it's not a register.
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002132///
Kevin Enderby8be42bd2009-10-30 22:55:57 +00002133/// TODO this is likely to change to allow different register types and or to
2134/// parse for a specific register type.
Bill Wendling2063b842010-11-18 23:43:05 +00002135bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002136tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattner44e5981c2010-10-30 04:09:10 +00002137 SMLoc S = Parser.getTok().getLoc();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002138 int RegNo = tryParseRegister();
Bill Wendlinge18980a2010-11-06 22:36:58 +00002139 if (RegNo == -1)
Bill Wendling2063b842010-11-18 23:43:05 +00002140 return true;
Jim Grosbach99710a82010-11-01 16:44:21 +00002141
Bill Wendling2063b842010-11-18 23:43:05 +00002142 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002143
Chris Lattner44e5981c2010-10-30 04:09:10 +00002144 const AsmToken &ExclaimTok = Parser.getTok();
2145 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling2063b842010-11-18 23:43:05 +00002146 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2147 ExclaimTok.getLoc()));
Chris Lattner44e5981c2010-10-30 04:09:10 +00002148 Parser.Lex(); // Eat exclaim token
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002149 return false;
2150 }
2151
2152 // Also check for an index operand. This is only legal for vector registers,
2153 // but that'll get caught OK in operand matching, so we don't need to
2154 // explicitly filter everything else out here.
2155 if (Parser.getTok().is(AsmToken::LBrac)) {
2156 SMLoc SIdx = Parser.getTok().getLoc();
2157 Parser.Lex(); // Eat left bracket token.
2158
2159 const MCExpr *ImmVal;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002160 if (getParser().ParseExpression(ImmVal))
2161 return MatchOperand_ParseFail;
2162 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2163 if (!MCE) {
2164 TokError("immediate value expected for vector index");
2165 return MatchOperand_ParseFail;
2166 }
2167
2168 SMLoc E = Parser.getTok().getLoc();
2169 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2170 Error(E, "']' expected");
2171 return MatchOperand_ParseFail;
2172 }
2173
2174 Parser.Lex(); // Eat right bracket token.
2175
2176 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2177 SIdx, E,
2178 getContext()));
Kevin Enderby2207e5f2009-10-07 18:01:35 +00002179 }
2180
Bill Wendling2063b842010-11-18 23:43:05 +00002181 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002182}
2183
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002184/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2185/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2186/// "c5", ...
2187static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002188 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2189 // but efficient.
2190 switch (Name.size()) {
2191 default: break;
2192 case 2:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002193 if (Name[0] != CoprocOp)
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002194 return -1;
2195 switch (Name[1]) {
2196 default: return -1;
2197 case '0': return 0;
2198 case '1': return 1;
2199 case '2': return 2;
2200 case '3': return 3;
2201 case '4': return 4;
2202 case '5': return 5;
2203 case '6': return 6;
2204 case '7': return 7;
2205 case '8': return 8;
2206 case '9': return 9;
2207 }
2208 break;
2209 case 3:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002210 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002211 return -1;
2212 switch (Name[2]) {
2213 default: return -1;
2214 case '0': return 10;
2215 case '1': return 11;
2216 case '2': return 12;
2217 case '3': return 13;
2218 case '4': return 14;
2219 case '5': return 15;
2220 }
2221 break;
2222 }
2223
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002224 return -1;
2225}
2226
Jim Grosbach3d1eac82011-08-26 21:43:41 +00002227/// parseITCondCode - Try to parse a condition code for an IT instruction.
2228ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2229parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2230 SMLoc S = Parser.getTok().getLoc();
2231 const AsmToken &Tok = Parser.getTok();
2232 if (!Tok.is(AsmToken::Identifier))
2233 return MatchOperand_NoMatch;
2234 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2235 .Case("eq", ARMCC::EQ)
2236 .Case("ne", ARMCC::NE)
2237 .Case("hs", ARMCC::HS)
2238 .Case("cs", ARMCC::HS)
2239 .Case("lo", ARMCC::LO)
2240 .Case("cc", ARMCC::LO)
2241 .Case("mi", ARMCC::MI)
2242 .Case("pl", ARMCC::PL)
2243 .Case("vs", ARMCC::VS)
2244 .Case("vc", ARMCC::VC)
2245 .Case("hi", ARMCC::HI)
2246 .Case("ls", ARMCC::LS)
2247 .Case("ge", ARMCC::GE)
2248 .Case("lt", ARMCC::LT)
2249 .Case("gt", ARMCC::GT)
2250 .Case("le", ARMCC::LE)
2251 .Case("al", ARMCC::AL)
2252 .Default(~0U);
2253 if (CC == ~0U)
2254 return MatchOperand_NoMatch;
2255 Parser.Lex(); // Eat the token.
2256
2257 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2258
2259 return MatchOperand_Success;
2260}
2261
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002262/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002263/// token must be an Identifier when called, and if it is a coprocessor
2264/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002265ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002266parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002267 SMLoc S = Parser.getTok().getLoc();
2268 const AsmToken &Tok = Parser.getTok();
Jim Grosbach54a20ed2011-10-12 20:54:17 +00002269 if (Tok.isNot(AsmToken::Identifier))
2270 return MatchOperand_NoMatch;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002271
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002272 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002273 if (Num == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002274 return MatchOperand_NoMatch;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002275
2276 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002277 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002278 return MatchOperand_Success;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002279}
2280
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002281/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002282/// token must be an Identifier when called, and if it is a coprocessor
2283/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002284ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002285parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002286 SMLoc S = Parser.getTok().getLoc();
2287 const AsmToken &Tok = Parser.getTok();
Jim Grosbach54a20ed2011-10-12 20:54:17 +00002288 if (Tok.isNot(AsmToken::Identifier))
2289 return MatchOperand_NoMatch;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002290
2291 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2292 if (Reg == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002293 return MatchOperand_NoMatch;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002294
2295 Parser.Lex(); // Eat identifier token.
2296 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002297 return MatchOperand_Success;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002298}
2299
Jim Grosbach48399582011-10-12 17:34:41 +00002300/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2301/// coproc_option : '{' imm0_255 '}'
2302ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2303parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2304 SMLoc S = Parser.getTok().getLoc();
2305
2306 // If this isn't a '{', this isn't a coprocessor immediate operand.
2307 if (Parser.getTok().isNot(AsmToken::LCurly))
2308 return MatchOperand_NoMatch;
2309 Parser.Lex(); // Eat the '{'
2310
2311 const MCExpr *Expr;
2312 SMLoc Loc = Parser.getTok().getLoc();
2313 if (getParser().ParseExpression(Expr)) {
2314 Error(Loc, "illegal expression");
2315 return MatchOperand_ParseFail;
2316 }
2317 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2318 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2319 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2320 return MatchOperand_ParseFail;
2321 }
2322 int Val = CE->getValue();
2323
2324 // Check for and consume the closing '}'
2325 if (Parser.getTok().isNot(AsmToken::RCurly))
2326 return MatchOperand_ParseFail;
2327 SMLoc E = Parser.getTok().getLoc();
2328 Parser.Lex(); // Eat the '}'
2329
2330 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2331 return MatchOperand_Success;
2332}
2333
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002334// For register list parsing, we need to map from raw GPR register numbering
2335// to the enumeration values. The enumeration values aren't sorted by
2336// register number due to our using "sp", "lr" and "pc" as canonical names.
2337static unsigned getNextRegister(unsigned Reg) {
2338 // If this is a GPR, we need to do it manually, otherwise we can rely
2339 // on the sort ordering of the enumeration since the other reg-classes
2340 // are sane.
2341 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2342 return Reg + 1;
2343 switch(Reg) {
2344 default: assert(0 && "Invalid GPR number!");
2345 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2346 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2347 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2348 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2349 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2350 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2351 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2352 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2353 }
2354}
2355
Jim Grosbach85a23432011-11-11 21:27:40 +00002356// Return the low-subreg of a given Q register.
2357static unsigned getDRegFromQReg(unsigned QReg) {
2358 switch (QReg) {
2359 default: llvm_unreachable("expected a Q register!");
2360 case ARM::Q0: return ARM::D0;
2361 case ARM::Q1: return ARM::D2;
2362 case ARM::Q2: return ARM::D4;
2363 case ARM::Q3: return ARM::D6;
2364 case ARM::Q4: return ARM::D8;
2365 case ARM::Q5: return ARM::D10;
2366 case ARM::Q6: return ARM::D12;
2367 case ARM::Q7: return ARM::D14;
2368 case ARM::Q8: return ARM::D16;
Jim Grosbacha92a5d82011-11-15 21:01:30 +00002369 case ARM::Q9: return ARM::D18;
Jim Grosbach85a23432011-11-11 21:27:40 +00002370 case ARM::Q10: return ARM::D20;
2371 case ARM::Q11: return ARM::D22;
2372 case ARM::Q12: return ARM::D24;
2373 case ARM::Q13: return ARM::D26;
2374 case ARM::Q14: return ARM::D28;
2375 case ARM::Q15: return ARM::D30;
2376 }
2377}
2378
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002379/// Parse a register list.
Bill Wendling2063b842010-11-18 23:43:05 +00002380bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002381parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan936b0d32010-01-19 21:44:56 +00002382 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00002383 "Token is not a Left Curly Brace");
Bill Wendlinge18980a2010-11-06 22:36:58 +00002384 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002385 Parser.Lex(); // Eat '{' token.
2386 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbya2b99102009-10-09 21:12:28 +00002387
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002388 // Check the first register in the list to see what register class
2389 // this is a list of.
2390 int Reg = tryParseRegister();
2391 if (Reg == -1)
2392 return Error(RegLoc, "register expected");
2393
Jim Grosbach85a23432011-11-11 21:27:40 +00002394 // The reglist instructions have at most 16 registers, so reserve
2395 // space for that many.
2396 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2397
2398 // Allow Q regs and just interpret them as the two D sub-registers.
2399 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2400 Reg = getDRegFromQReg(Reg);
2401 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2402 ++Reg;
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
Jim Grosbach85a23432011-11-11 21:27:40 +00002414 // Store the register.
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002415 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbya2b99102009-10-09 21:12:28 +00002416
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002417 // This starts immediately after the first register token in the list,
2418 // so we can see either a comma or a minus (range separator) as a legal
2419 // next token.
2420 while (Parser.getTok().is(AsmToken::Comma) ||
2421 Parser.getTok().is(AsmToken::Minus)) {
2422 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache891fe82011-11-15 23:19:15 +00002423 Parser.Lex(); // Eat the minus.
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002424 SMLoc EndLoc = Parser.getTok().getLoc();
2425 int EndReg = tryParseRegister();
2426 if (EndReg == -1)
2427 return Error(EndLoc, "register expected");
Jim Grosbach85a23432011-11-11 21:27:40 +00002428 // Allow Q regs and just interpret them as the two D sub-registers.
2429 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2430 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002431 // 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 Grosbach85a23432011-11-11 21:27:40 +00002455 // Allow Q regs and just interpret them as the two D sub-registers.
2456 bool isQReg = false;
2457 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2458 Reg = getDRegFromQReg(Reg);
2459 isQReg = true;
2460 }
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002461 // The register must be in the same register class as the first.
2462 if (!RC->contains(Reg))
2463 return Error(RegLoc, "invalid register in register list");
2464 // List must be monotonically increasing.
2465 if (getARMRegisterNumbering(Reg) <= getARMRegisterNumbering(OldReg))
2466 return Error(RegLoc, "register list not in ascending order");
2467 // VFP register lists must also be contiguous.
2468 // It's OK to use the enumeration values directly here rather, as the
2469 // VFP register classes have the enum sorted properly.
2470 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2471 Reg != OldReg + 1)
2472 return Error(RegLoc, "non-contiguous register range");
2473 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbach85a23432011-11-11 21:27:40 +00002474 if (isQReg)
2475 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge18980a2010-11-06 22:36:58 +00002476 }
2477
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002478 SMLoc E = Parser.getTok().getLoc();
2479 if (Parser.getTok().isNot(AsmToken::RCurly))
2480 return Error(E, "'}' expected");
2481 Parser.Lex(); // Eat '}' token.
2482
Bill Wendling2063b842010-11-18 23:43:05 +00002483 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2484 return false;
Kevin Enderbya2b99102009-10-09 21:12:28 +00002485}
2486
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002487// parse a vector register list
2488ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2489parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach8d579232011-11-15 21:45:55 +00002490 SMLoc S = Parser.getTok().getLoc();
2491 // As an extension (to match gas), support a plain D register or Q register
2492 // (without encosing curly braces) as a single or double entry list,
2493 // respectively.
2494 if (Parser.getTok().is(AsmToken::Identifier)) {
2495 int Reg = tryParseRegister();
2496 if (Reg == -1)
2497 return MatchOperand_NoMatch;
2498 SMLoc E = Parser.getTok().getLoc();
2499 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
2500 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, S, E));
2501 return MatchOperand_Success;
2502 }
2503 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2504 Reg = getDRegFromQReg(Reg);
2505 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, S, E));
2506 return MatchOperand_Success;
2507 }
2508 Error(S, "vector register expected");
2509 return MatchOperand_ParseFail;
2510 }
2511
2512 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002513 return MatchOperand_NoMatch;
2514
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002515 Parser.Lex(); // Eat '{' token.
2516 SMLoc RegLoc = Parser.getTok().getLoc();
2517
2518 int Reg = tryParseRegister();
2519 if (Reg == -1) {
2520 Error(RegLoc, "register expected");
2521 return MatchOperand_ParseFail;
2522 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002523 unsigned Count = 1;
Jim Grosbach080a4992011-10-28 00:06:50 +00002524 unsigned FirstReg = Reg;
2525 // The list is of D registers, but we also allow Q regs and just interpret
2526 // them as the two D sub-registers.
2527 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2528 FirstReg = Reg = getDRegFromQReg(Reg);
2529 ++Reg;
2530 ++Count;
2531 }
2532
Jim Grosbache891fe82011-11-15 23:19:15 +00002533 while (Parser.getTok().is(AsmToken::Comma) ||
2534 Parser.getTok().is(AsmToken::Minus)) {
2535 if (Parser.getTok().is(AsmToken::Minus)) {
2536 Parser.Lex(); // Eat the minus.
2537 SMLoc EndLoc = Parser.getTok().getLoc();
2538 int EndReg = tryParseRegister();
2539 if (EndReg == -1) {
2540 Error(EndLoc, "register expected");
2541 return MatchOperand_ParseFail;
2542 }
2543 // Allow Q regs and just interpret them as the two D sub-registers.
2544 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2545 EndReg = getDRegFromQReg(EndReg) + 1;
2546 // If the register is the same as the start reg, there's nothing
2547 // more to do.
2548 if (Reg == EndReg)
2549 continue;
2550 // The register must be in the same register class as the first.
2551 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
2552 Error(EndLoc, "invalid register in register list");
2553 return MatchOperand_ParseFail;
2554 }
2555 // Ranges must go from low to high.
2556 if (Reg > EndReg) {
2557 Error(EndLoc, "bad range in register list");
2558 return MatchOperand_ParseFail;
2559 }
2560
2561 // Add all the registers in the range to the register list.
2562 Count += EndReg - Reg;
2563 Reg = EndReg;
2564 continue;
2565 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002566 Parser.Lex(); // Eat the comma.
2567 RegLoc = Parser.getTok().getLoc();
2568 int OldReg = Reg;
2569 Reg = tryParseRegister();
2570 if (Reg == -1) {
2571 Error(RegLoc, "register expected");
2572 return MatchOperand_ParseFail;
2573 }
Jim Grosbach080a4992011-10-28 00:06:50 +00002574 // vector register lists must be contiguous.
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002575 // It's OK to use the enumeration values directly here rather, as the
2576 // VFP register classes have the enum sorted properly.
Jim Grosbach080a4992011-10-28 00:06:50 +00002577 //
2578 // The list is of D registers, but we also allow Q regs and just interpret
2579 // them as the two D sub-registers.
2580 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2581 Reg = getDRegFromQReg(Reg);
2582 if (Reg != OldReg + 1) {
2583 Error(RegLoc, "non-contiguous register range");
2584 return MatchOperand_ParseFail;
2585 }
2586 ++Reg;
2587 Count += 2;
2588 continue;
2589 }
2590 // Normal D register. Just check that it's contiguous and keep going.
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002591 if (Reg != OldReg + 1) {
2592 Error(RegLoc, "non-contiguous register range");
2593 return MatchOperand_ParseFail;
2594 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002595 ++Count;
2596 }
2597
2598 SMLoc E = Parser.getTok().getLoc();
2599 if (Parser.getTok().isNot(AsmToken::RCurly)) {
2600 Error(E, "'}' expected");
2601 return MatchOperand_ParseFail;
2602 }
2603 Parser.Lex(); // Eat '}' token.
2604
2605 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count, S, E));
2606 return MatchOperand_Success;
2607}
2608
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002609/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002610ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002611parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002612 SMLoc S = Parser.getTok().getLoc();
2613 const AsmToken &Tok = Parser.getTok();
2614 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2615 StringRef OptStr = Tok.getString();
2616
2617 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2618 .Case("sy", ARM_MB::SY)
2619 .Case("st", ARM_MB::ST)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002620 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002621 .Case("ish", ARM_MB::ISH)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002622 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002623 .Case("ishst", ARM_MB::ISHST)
2624 .Case("nsh", ARM_MB::NSH)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002625 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002626 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002627 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002628 .Case("osh", ARM_MB::OSH)
2629 .Case("oshst", ARM_MB::OSHST)
2630 .Default(~0U);
2631
2632 if (Opt == ~0U)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002633 return MatchOperand_NoMatch;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002634
2635 Parser.Lex(); // Eat identifier token.
2636 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002637 return MatchOperand_Success;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002638}
2639
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002640/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002641ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002642parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002643 SMLoc S = Parser.getTok().getLoc();
2644 const AsmToken &Tok = Parser.getTok();
2645 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2646 StringRef IFlagsStr = Tok.getString();
2647
Owen Anderson10c5b122011-10-05 17:16:40 +00002648 // An iflags string of "none" is interpreted to mean that none of the AIF
2649 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002650 unsigned IFlags = 0;
Owen Anderson10c5b122011-10-05 17:16:40 +00002651 if (IFlagsStr != "none") {
2652 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2653 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2654 .Case("a", ARM_PROC::A)
2655 .Case("i", ARM_PROC::I)
2656 .Case("f", ARM_PROC::F)
2657 .Default(~0U);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002658
Owen Anderson10c5b122011-10-05 17:16:40 +00002659 // If some specific iflag is already set, it means that some letter is
2660 // present more than once, this is not acceptable.
2661 if (Flag == ~0U || (IFlags & Flag))
2662 return MatchOperand_NoMatch;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002663
Owen Anderson10c5b122011-10-05 17:16:40 +00002664 IFlags |= Flag;
2665 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002666 }
2667
2668 Parser.Lex(); // Eat identifier token.
2669 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2670 return MatchOperand_Success;
2671}
2672
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002673/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002674ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002675parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002676 SMLoc S = Parser.getTok().getLoc();
2677 const AsmToken &Tok = Parser.getTok();
2678 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2679 StringRef Mask = Tok.getString();
2680
James Molloy21efa7d2011-09-28 14:21:38 +00002681 if (isMClass()) {
2682 // See ARMv6-M 10.1.1
2683 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2684 .Case("apsr", 0)
2685 .Case("iapsr", 1)
2686 .Case("eapsr", 2)
2687 .Case("xpsr", 3)
2688 .Case("ipsr", 5)
2689 .Case("epsr", 6)
2690 .Case("iepsr", 7)
2691 .Case("msp", 8)
2692 .Case("psp", 9)
2693 .Case("primask", 16)
2694 .Case("basepri", 17)
2695 .Case("basepri_max", 18)
2696 .Case("faultmask", 19)
2697 .Case("control", 20)
2698 .Default(~0U);
2699
2700 if (FlagsVal == ~0U)
2701 return MatchOperand_NoMatch;
2702
2703 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
2704 // basepri, basepri_max and faultmask only valid for V7m.
2705 return MatchOperand_NoMatch;
2706
2707 Parser.Lex(); // Eat identifier token.
2708 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2709 return MatchOperand_Success;
2710 }
2711
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002712 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
2713 size_t Start = 0, Next = Mask.find('_');
2714 StringRef Flags = "";
Benjamin Kramer20baffb2011-11-06 20:37:06 +00002715 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002716 if (Next != StringRef::npos)
2717 Flags = Mask.slice(Next+1, Mask.size());
2718
2719 // FlagsVal contains the complete mask:
2720 // 3-0: Mask
2721 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2722 unsigned FlagsVal = 0;
2723
2724 if (SpecReg == "apsr") {
2725 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachd25c2cd2011-07-19 22:45:10 +00002726 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002727 .Case("g", 0x4) // same as CPSR_s
2728 .Case("nzcvqg", 0xc) // same as CPSR_fs
2729 .Default(~0U);
2730
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00002731 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002732 if (!Flags.empty())
2733 return MatchOperand_NoMatch;
2734 else
Jim Grosbach0ecd3952011-09-14 20:03:46 +00002735 FlagsVal = 8; // No flag
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00002736 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002737 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes54452132011-05-25 00:35:03 +00002738 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
2739 Flags = "fc";
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002740 for (int i = 0, e = Flags.size(); i != e; ++i) {
2741 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
2742 .Case("c", 1)
2743 .Case("x", 2)
2744 .Case("s", 4)
2745 .Case("f", 8)
2746 .Default(~0U);
2747
2748 // If some specific flag is already set, it means that some letter is
2749 // present more than once, this is not acceptable.
2750 if (FlagsVal == ~0U || (FlagsVal & Flag))
2751 return MatchOperand_NoMatch;
2752 FlagsVal |= Flag;
2753 }
2754 } else // No match for special register.
2755 return MatchOperand_NoMatch;
2756
Owen Anderson03a173e2011-10-21 18:43:28 +00002757 // Special register without flags is NOT equivalent to "fc" flags.
2758 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
2759 // two lines would enable gas compatibility at the expense of breaking
2760 // round-tripping.
2761 //
2762 // if (!FlagsVal)
2763 // FlagsVal = 0x9;
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002764
2765 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2766 if (SpecReg == "spsr")
2767 FlagsVal |= 16;
2768
2769 Parser.Lex(); // Eat identifier token.
2770 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2771 return MatchOperand_Success;
2772}
2773
Jim Grosbach27c1e252011-07-21 17:23:04 +00002774ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2775parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
2776 int Low, int High) {
2777 const AsmToken &Tok = Parser.getTok();
2778 if (Tok.isNot(AsmToken::Identifier)) {
2779 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2780 return MatchOperand_ParseFail;
2781 }
2782 StringRef ShiftName = Tok.getString();
Benjamin Kramer20baffb2011-11-06 20:37:06 +00002783 std::string LowerOp = Op.lower();
2784 std::string UpperOp = Op.upper();
Jim Grosbach27c1e252011-07-21 17:23:04 +00002785 if (ShiftName != LowerOp && ShiftName != UpperOp) {
2786 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2787 return MatchOperand_ParseFail;
2788 }
2789 Parser.Lex(); // Eat shift type token.
2790
2791 // There must be a '#' and a shift amount.
2792 if (Parser.getTok().isNot(AsmToken::Hash)) {
2793 Error(Parser.getTok().getLoc(), "'#' expected");
2794 return MatchOperand_ParseFail;
2795 }
2796 Parser.Lex(); // Eat hash token.
2797
2798 const MCExpr *ShiftAmount;
2799 SMLoc Loc = Parser.getTok().getLoc();
2800 if (getParser().ParseExpression(ShiftAmount)) {
2801 Error(Loc, "illegal expression");
2802 return MatchOperand_ParseFail;
2803 }
2804 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2805 if (!CE) {
2806 Error(Loc, "constant expression expected");
2807 return MatchOperand_ParseFail;
2808 }
2809 int Val = CE->getValue();
2810 if (Val < Low || Val > High) {
2811 Error(Loc, "immediate value out of range");
2812 return MatchOperand_ParseFail;
2813 }
2814
2815 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
2816
2817 return MatchOperand_Success;
2818}
2819
Jim Grosbach0a547702011-07-22 17:44:50 +00002820ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2821parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2822 const AsmToken &Tok = Parser.getTok();
2823 SMLoc S = Tok.getLoc();
2824 if (Tok.isNot(AsmToken::Identifier)) {
2825 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2826 return MatchOperand_ParseFail;
2827 }
2828 int Val = StringSwitch<int>(Tok.getString())
2829 .Case("be", 1)
2830 .Case("le", 0)
2831 .Default(-1);
2832 Parser.Lex(); // Eat the token.
2833
2834 if (Val == -1) {
2835 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2836 return MatchOperand_ParseFail;
2837 }
2838 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
2839 getContext()),
2840 S, Parser.getTok().getLoc()));
2841 return MatchOperand_Success;
2842}
2843
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002844/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
2845/// instructions. Legal values are:
2846/// lsl #n 'n' in [0,31]
2847/// asr #n 'n' in [1,32]
2848/// n == 32 encoded as n == 0.
2849ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2850parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2851 const AsmToken &Tok = Parser.getTok();
2852 SMLoc S = Tok.getLoc();
2853 if (Tok.isNot(AsmToken::Identifier)) {
2854 Error(S, "shift operator 'asr' or 'lsl' expected");
2855 return MatchOperand_ParseFail;
2856 }
2857 StringRef ShiftName = Tok.getString();
2858 bool isASR;
2859 if (ShiftName == "lsl" || ShiftName == "LSL")
2860 isASR = false;
2861 else if (ShiftName == "asr" || ShiftName == "ASR")
2862 isASR = true;
2863 else {
2864 Error(S, "shift operator 'asr' or 'lsl' expected");
2865 return MatchOperand_ParseFail;
2866 }
2867 Parser.Lex(); // Eat the operator.
2868
2869 // A '#' and a shift amount.
2870 if (Parser.getTok().isNot(AsmToken::Hash)) {
2871 Error(Parser.getTok().getLoc(), "'#' expected");
2872 return MatchOperand_ParseFail;
2873 }
2874 Parser.Lex(); // Eat hash token.
2875
2876 const MCExpr *ShiftAmount;
2877 SMLoc E = Parser.getTok().getLoc();
2878 if (getParser().ParseExpression(ShiftAmount)) {
2879 Error(E, "malformed shift expression");
2880 return MatchOperand_ParseFail;
2881 }
2882 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2883 if (!CE) {
2884 Error(E, "shift amount must be an immediate");
2885 return MatchOperand_ParseFail;
2886 }
2887
2888 int64_t Val = CE->getValue();
2889 if (isASR) {
2890 // Shift amount must be in [1,32]
2891 if (Val < 1 || Val > 32) {
2892 Error(E, "'asr' shift amount must be in range [1,32]");
2893 return MatchOperand_ParseFail;
2894 }
Owen Andersonf01e2de2011-09-26 21:06:22 +00002895 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
2896 if (isThumb() && Val == 32) {
2897 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
2898 return MatchOperand_ParseFail;
2899 }
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002900 if (Val == 32) Val = 0;
2901 } else {
2902 // Shift amount must be in [1,32]
2903 if (Val < 0 || Val > 31) {
2904 Error(E, "'lsr' shift amount must be in range [0,31]");
2905 return MatchOperand_ParseFail;
2906 }
2907 }
2908
2909 E = Parser.getTok().getLoc();
2910 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
2911
2912 return MatchOperand_Success;
2913}
2914
Jim Grosbach833b9d32011-07-27 20:15:40 +00002915/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
2916/// of instructions. Legal values are:
2917/// ror #n 'n' in {0, 8, 16, 24}
2918ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2919parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2920 const AsmToken &Tok = Parser.getTok();
2921 SMLoc S = Tok.getLoc();
Jim Grosbach82213192011-09-19 20:29:33 +00002922 if (Tok.isNot(AsmToken::Identifier))
2923 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00002924 StringRef ShiftName = Tok.getString();
Jim Grosbach82213192011-09-19 20:29:33 +00002925 if (ShiftName != "ror" && ShiftName != "ROR")
2926 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00002927 Parser.Lex(); // Eat the operator.
2928
2929 // A '#' and a rotate amount.
2930 if (Parser.getTok().isNot(AsmToken::Hash)) {
2931 Error(Parser.getTok().getLoc(), "'#' expected");
2932 return MatchOperand_ParseFail;
2933 }
2934 Parser.Lex(); // Eat hash token.
2935
2936 const MCExpr *ShiftAmount;
2937 SMLoc E = Parser.getTok().getLoc();
2938 if (getParser().ParseExpression(ShiftAmount)) {
2939 Error(E, "malformed rotate expression");
2940 return MatchOperand_ParseFail;
2941 }
2942 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2943 if (!CE) {
2944 Error(E, "rotate amount must be an immediate");
2945 return MatchOperand_ParseFail;
2946 }
2947
2948 int64_t Val = CE->getValue();
2949 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
2950 // normally, zero is represented in asm by omitting the rotate operand
2951 // entirely.
2952 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
2953 Error(E, "'ror' rotate amount must be 8, 16, or 24");
2954 return MatchOperand_ParseFail;
2955 }
2956
2957 E = Parser.getTok().getLoc();
2958 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
2959
2960 return MatchOperand_Success;
2961}
2962
Jim Grosbach864b6092011-07-28 21:34:26 +00002963ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2964parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2965 SMLoc S = Parser.getTok().getLoc();
2966 // The bitfield descriptor is really two operands, the LSB and the width.
2967 if (Parser.getTok().isNot(AsmToken::Hash)) {
2968 Error(Parser.getTok().getLoc(), "'#' expected");
2969 return MatchOperand_ParseFail;
2970 }
2971 Parser.Lex(); // Eat hash token.
2972
2973 const MCExpr *LSBExpr;
2974 SMLoc E = Parser.getTok().getLoc();
2975 if (getParser().ParseExpression(LSBExpr)) {
2976 Error(E, "malformed immediate expression");
2977 return MatchOperand_ParseFail;
2978 }
2979 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
2980 if (!CE) {
2981 Error(E, "'lsb' operand must be an immediate");
2982 return MatchOperand_ParseFail;
2983 }
2984
2985 int64_t LSB = CE->getValue();
2986 // The LSB must be in the range [0,31]
2987 if (LSB < 0 || LSB > 31) {
2988 Error(E, "'lsb' operand must be in the range [0,31]");
2989 return MatchOperand_ParseFail;
2990 }
2991 E = Parser.getTok().getLoc();
2992
2993 // Expect another immediate operand.
2994 if (Parser.getTok().isNot(AsmToken::Comma)) {
2995 Error(Parser.getTok().getLoc(), "too few operands");
2996 return MatchOperand_ParseFail;
2997 }
2998 Parser.Lex(); // Eat hash token.
2999 if (Parser.getTok().isNot(AsmToken::Hash)) {
3000 Error(Parser.getTok().getLoc(), "'#' expected");
3001 return MatchOperand_ParseFail;
3002 }
3003 Parser.Lex(); // Eat hash token.
3004
3005 const MCExpr *WidthExpr;
3006 if (getParser().ParseExpression(WidthExpr)) {
3007 Error(E, "malformed immediate expression");
3008 return MatchOperand_ParseFail;
3009 }
3010 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3011 if (!CE) {
3012 Error(E, "'width' operand must be an immediate");
3013 return MatchOperand_ParseFail;
3014 }
3015
3016 int64_t Width = CE->getValue();
3017 // The LSB must be in the range [1,32-lsb]
3018 if (Width < 1 || Width > 32 - LSB) {
3019 Error(E, "'width' operand must be in the range [1,32-lsb]");
3020 return MatchOperand_ParseFail;
3021 }
3022 E = Parser.getTok().getLoc();
3023
3024 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3025
3026 return MatchOperand_Success;
3027}
3028
Jim Grosbachd3595712011-08-03 23:50:40 +00003029ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3030parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3031 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachc320c852011-08-05 21:28:30 +00003032 // postidx_reg := '+' register {, shift}
3033 // | '-' register {, shift}
3034 // | register {, shift}
Jim Grosbachd3595712011-08-03 23:50:40 +00003035
3036 // This method must return MatchOperand_NoMatch without consuming any tokens
3037 // in the case where there is no match, as other alternatives take other
3038 // parse methods.
3039 AsmToken Tok = Parser.getTok();
3040 SMLoc S = Tok.getLoc();
3041 bool haveEaten = false;
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00003042 bool isAdd = true;
Jim Grosbachd3595712011-08-03 23:50:40 +00003043 int Reg = -1;
3044 if (Tok.is(AsmToken::Plus)) {
3045 Parser.Lex(); // Eat the '+' token.
3046 haveEaten = true;
3047 } else if (Tok.is(AsmToken::Minus)) {
3048 Parser.Lex(); // Eat the '-' token.
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00003049 isAdd = false;
Jim Grosbachd3595712011-08-03 23:50:40 +00003050 haveEaten = true;
3051 }
3052 if (Parser.getTok().is(AsmToken::Identifier))
3053 Reg = tryParseRegister();
3054 if (Reg == -1) {
3055 if (!haveEaten)
3056 return MatchOperand_NoMatch;
3057 Error(Parser.getTok().getLoc(), "register expected");
3058 return MatchOperand_ParseFail;
3059 }
3060 SMLoc E = Parser.getTok().getLoc();
3061
Jim Grosbachc320c852011-08-05 21:28:30 +00003062 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3063 unsigned ShiftImm = 0;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00003064 if (Parser.getTok().is(AsmToken::Comma)) {
3065 Parser.Lex(); // Eat the ','.
3066 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3067 return MatchOperand_ParseFail;
3068 }
Jim Grosbachc320c852011-08-05 21:28:30 +00003069
3070 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3071 ShiftImm, S, E));
Jim Grosbachd3595712011-08-03 23:50:40 +00003072
3073 return MatchOperand_Success;
3074}
3075
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00003076ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3077parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3078 // Check for a post-index addressing register operand. Specifically:
3079 // am3offset := '+' register
3080 // | '-' register
3081 // | register
3082 // | # imm
3083 // | # + imm
3084 // | # - imm
3085
3086 // This method must return MatchOperand_NoMatch without consuming any tokens
3087 // in the case where there is no match, as other alternatives take other
3088 // parse methods.
3089 AsmToken Tok = Parser.getTok();
3090 SMLoc S = Tok.getLoc();
3091
3092 // Do immediates first, as we always parse those if we have a '#'.
3093 if (Parser.getTok().is(AsmToken::Hash)) {
3094 Parser.Lex(); // Eat the '#'.
3095 // Explicitly look for a '-', as we need to encode negative zero
3096 // differently.
3097 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3098 const MCExpr *Offset;
3099 if (getParser().ParseExpression(Offset))
3100 return MatchOperand_ParseFail;
3101 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3102 if (!CE) {
3103 Error(S, "constant expression expected");
3104 return MatchOperand_ParseFail;
3105 }
3106 SMLoc E = Tok.getLoc();
3107 // Negative zero is encoded as the flag value INT32_MIN.
3108 int32_t Val = CE->getValue();
3109 if (isNegative && Val == 0)
3110 Val = INT32_MIN;
3111
3112 Operands.push_back(
3113 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3114
3115 return MatchOperand_Success;
3116 }
3117
3118
3119 bool haveEaten = false;
3120 bool isAdd = true;
3121 int Reg = -1;
3122 if (Tok.is(AsmToken::Plus)) {
3123 Parser.Lex(); // Eat the '+' token.
3124 haveEaten = true;
3125 } else if (Tok.is(AsmToken::Minus)) {
3126 Parser.Lex(); // Eat the '-' token.
3127 isAdd = false;
3128 haveEaten = true;
3129 }
3130 if (Parser.getTok().is(AsmToken::Identifier))
3131 Reg = tryParseRegister();
3132 if (Reg == -1) {
3133 if (!haveEaten)
3134 return MatchOperand_NoMatch;
3135 Error(Parser.getTok().getLoc(), "register expected");
3136 return MatchOperand_ParseFail;
3137 }
3138 SMLoc E = Parser.getTok().getLoc();
3139
3140 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3141 0, S, E));
3142
3143 return MatchOperand_Success;
3144}
3145
Jim Grosbach7db8d692011-09-08 22:07:06 +00003146/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3147/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3148/// when they refer multiple MIOperands inside a single one.
3149bool ARMAsmParser::
3150cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3151 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3152 // Rt, Rt2
3153 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3154 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3155 // Create a writeback register dummy placeholder.
3156 Inst.addOperand(MCOperand::CreateReg(0));
3157 // addr
3158 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3159 // pred
3160 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3161 return true;
3162}
3163
3164/// cvtT2StrdPre - Convert parsed operands to MCInst.
3165/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3166/// when they refer multiple MIOperands inside a single one.
3167bool ARMAsmParser::
3168cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3169 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3170 // Create a writeback register dummy placeholder.
3171 Inst.addOperand(MCOperand::CreateReg(0));
3172 // Rt, Rt2
3173 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3174 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3175 // addr
3176 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3177 // pred
3178 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3179 return true;
3180}
3181
Jim Grosbachc086f682011-09-08 00:39:19 +00003182/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3183/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3184/// when they refer multiple MIOperands inside a single one.
3185bool ARMAsmParser::
3186cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3187 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3188 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3189
3190 // Create a writeback register dummy placeholder.
3191 Inst.addOperand(MCOperand::CreateImm(0));
3192
3193 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3194 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3195 return true;
3196}
3197
Jim Grosbach9c0b86a2011-09-16 21:55:56 +00003198/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3199/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3200/// when they refer multiple MIOperands inside a single one.
3201bool ARMAsmParser::
3202cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3203 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3204 // Create a writeback register dummy placeholder.
3205 Inst.addOperand(MCOperand::CreateImm(0));
3206 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3207 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3208 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3209 return true;
3210}
3211
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003212/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003213/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3214/// when they refer multiple MIOperands inside a single one.
3215bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003216cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003217 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3218 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3219
3220 // Create a writeback register dummy placeholder.
3221 Inst.addOperand(MCOperand::CreateImm(0));
3222
Jim Grosbachd3595712011-08-03 23:50:40 +00003223 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003224 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3225 return true;
3226}
3227
Owen Anderson16d33f32011-08-26 20:43:14 +00003228/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3229/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3230/// when they refer multiple MIOperands inside a single one.
3231bool ARMAsmParser::
3232cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3233 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3234 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3235
3236 // Create a writeback register dummy placeholder.
3237 Inst.addOperand(MCOperand::CreateImm(0));
3238
3239 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3240 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3241 return true;
3242}
3243
3244
Jim Grosbachd564bf32011-08-11 19:22:40 +00003245/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3246/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3247/// when they refer multiple MIOperands inside a single one.
3248bool ARMAsmParser::
3249cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3250 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3251 // Create a writeback register dummy placeholder.
3252 Inst.addOperand(MCOperand::CreateImm(0));
3253 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3254 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3255 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3256 return true;
3257}
3258
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003259/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003260/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3261/// when they refer multiple MIOperands inside a single one.
3262bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003263cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003264 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3265 // Create a writeback register dummy placeholder.
3266 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd564bf32011-08-11 19:22:40 +00003267 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3268 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3269 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbachd3595712011-08-03 23:50:40 +00003270 return true;
3271}
3272
Jim Grosbachd886f8c2011-08-11 21:17:22 +00003273/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3274/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3275/// when they refer multiple MIOperands inside a single one.
3276bool ARMAsmParser::
3277cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3278 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3279 // Create a writeback register dummy placeholder.
3280 Inst.addOperand(MCOperand::CreateImm(0));
3281 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3282 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3283 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3284 return true;
3285}
3286
Jim Grosbachd3595712011-08-03 23:50:40 +00003287/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3288/// 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::
3291cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3292 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3293 // Rt
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003294 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbachd3595712011-08-03 23:50:40 +00003295 // Create a writeback register dummy placeholder.
3296 Inst.addOperand(MCOperand::CreateImm(0));
3297 // addr
3298 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3299 // offset
3300 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3301 // pred
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003302 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3303 return true;
3304}
3305
Jim Grosbachd3595712011-08-03 23:50:40 +00003306/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003307/// 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::
Jim Grosbachd3595712011-08-03 23:50:40 +00003310cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3311 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3312 // Rt
Owen Andersonb0e68992011-07-28 17:18:57 +00003313 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003314 // Create a writeback register dummy placeholder.
3315 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd3595712011-08-03 23:50:40 +00003316 // 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 Grosbachd3595712011-08-03 23:50:40 +00003325/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003326/// 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::
Jim Grosbachd3595712011-08-03 23:50:40 +00003329cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3330 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003331 // Create a writeback register dummy placeholder.
3332 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd3595712011-08-03 23:50:40 +00003333 // Rt
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003334 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbachd3595712011-08-03 23:50:40 +00003335 // addr
3336 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3337 // offset
3338 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3339 // pred
3340 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3341 return true;
3342}
3343
3344/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3345/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3346/// when they refer multiple MIOperands inside a single one.
3347bool ARMAsmParser::
3348cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3349 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3350 // Create a writeback register dummy placeholder.
3351 Inst.addOperand(MCOperand::CreateImm(0));
3352 // Rt
3353 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3354 // addr
3355 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3356 // offset
3357 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3358 // pred
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003359 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3360 return true;
3361}
3362
Jim Grosbach5b96b802011-08-10 20:29:19 +00003363/// cvtLdrdPre - Convert parsed operands to MCInst.
3364/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3365/// when they refer multiple MIOperands inside a single one.
3366bool ARMAsmParser::
3367cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3368 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3369 // Rt, Rt2
3370 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3371 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3372 // Create a writeback register dummy placeholder.
3373 Inst.addOperand(MCOperand::CreateImm(0));
3374 // addr
3375 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3376 // pred
3377 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3378 return true;
3379}
3380
Jim Grosbacheb09f492011-08-11 20:28:23 +00003381/// cvtStrdPre - Convert parsed operands to MCInst.
3382/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3383/// when they refer multiple MIOperands inside a single one.
3384bool ARMAsmParser::
3385cvtStrdPre(MCInst &Inst, unsigned Opcode,
3386 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3387 // Create a writeback register dummy placeholder.
3388 Inst.addOperand(MCOperand::CreateImm(0));
3389 // Rt, Rt2
3390 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3391 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3392 // addr
3393 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3394 // pred
3395 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3396 return true;
3397}
3398
Jim Grosbachcd4dd252011-08-10 22:42:16 +00003399/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3400/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3401/// when they refer multiple MIOperands inside a single one.
3402bool ARMAsmParser::
3403cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3404 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3405 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3406 // Create a writeback register dummy placeholder.
3407 Inst.addOperand(MCOperand::CreateImm(0));
3408 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3409 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3410 return true;
3411}
3412
Jim Grosbach8e048492011-08-19 22:07:46 +00003413/// cvtThumbMultiple- Convert parsed operands to MCInst.
3414/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3415/// when they refer multiple MIOperands inside a single one.
3416bool ARMAsmParser::
3417cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3418 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3419 // The second source operand must be the same register as the destination
3420 // operand.
3421 if (Operands.size() == 6 &&
Jim Grosbach459422d2011-08-19 22:30:46 +00003422 (((ARMOperand*)Operands[3])->getReg() !=
3423 ((ARMOperand*)Operands[5])->getReg()) &&
3424 (((ARMOperand*)Operands[3])->getReg() !=
3425 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach8e048492011-08-19 22:07:46 +00003426 Error(Operands[3]->getStartLoc(),
Jim Grosbach459422d2011-08-19 22:30:46 +00003427 "destination register must match source register");
Jim Grosbach8e048492011-08-19 22:07:46 +00003428 return false;
3429 }
3430 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3431 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach5a5ce632011-11-10 22:10:12 +00003432 // If we have a three-operand form, make sure to set Rn to be the operand
3433 // that isn't the same as Rd.
3434 unsigned RegOp = 4;
3435 if (Operands.size() == 6 &&
3436 ((ARMOperand*)Operands[4])->getReg() ==
3437 ((ARMOperand*)Operands[3])->getReg())
3438 RegOp = 5;
3439 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
3440 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach8e048492011-08-19 22:07:46 +00003441 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3442
3443 return true;
3444}
Jim Grosbachcd4dd252011-08-10 22:42:16 +00003445
Jim Grosbach3ea06572011-10-24 22:16:58 +00003446bool ARMAsmParser::
3447cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3448 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3449 // Vd
3450 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3451 // Create a writeback register dummy placeholder.
3452 Inst.addOperand(MCOperand::CreateImm(0));
3453 // Vn
3454 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3455 // pred
3456 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3457 return true;
3458}
3459
3460bool ARMAsmParser::
3461cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3462 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3463 // Vd
3464 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3465 // Create a writeback register dummy placeholder.
3466 Inst.addOperand(MCOperand::CreateImm(0));
3467 // Vn
3468 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3469 // Vm
3470 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3471 // pred
3472 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3473 return true;
3474}
3475
Jim Grosbach05df4602011-10-31 21:50:31 +00003476bool ARMAsmParser::
3477cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
3478 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3479 // Create a writeback register dummy placeholder.
3480 Inst.addOperand(MCOperand::CreateImm(0));
3481 // Vn
3482 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3483 // Vt
3484 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3485 // pred
3486 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3487 return true;
3488}
3489
3490bool ARMAsmParser::
3491cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
3492 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3493 // Create a writeback register dummy placeholder.
3494 Inst.addOperand(MCOperand::CreateImm(0));
3495 // Vn
3496 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3497 // Vm
3498 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3499 // Vt
3500 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3501 // pred
3502 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3503 return true;
3504}
3505
Bill Wendlinge18980a2010-11-06 22:36:58 +00003506/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003507/// or an error. The first token must be a '[' when called.
Bill Wendling2063b842010-11-18 23:43:05 +00003508bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003509parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003510 SMLoc S, E;
Sean Callanan936b0d32010-01-19 21:44:56 +00003511 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00003512 "Token is not a Left Bracket");
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003513 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00003514 Parser.Lex(); // Eat left bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003515
Sean Callanan936b0d32010-01-19 21:44:56 +00003516 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003517 int BaseRegNum = tryParseRegister();
Jim Grosbachd3595712011-08-03 23:50:40 +00003518 if (BaseRegNum == -1)
3519 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003520
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00003521 // The next token must either be a comma or a closing bracket.
3522 const AsmToken &Tok = Parser.getTok();
3523 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbachd3595712011-08-03 23:50:40 +00003524 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00003525
Jim Grosbachd3595712011-08-03 23:50:40 +00003526 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003527 E = Tok.getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00003528 Parser.Lex(); // Eat right bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003529
Jim Grosbachd3595712011-08-03 23:50:40 +00003530 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbacha95ec992011-10-11 17:29:55 +00003531 0, 0, false, S, E));
Jim Grosbach32ff5582010-11-29 23:18:01 +00003532
Jim Grosbach40700e02011-09-19 18:42:21 +00003533 // If there's a pre-indexing writeback marker, '!', just add it as a token
3534 // operand. It's rather odd, but syntactically valid.
3535 if (Parser.getTok().is(AsmToken::Exclaim)) {
3536 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3537 Parser.Lex(); // Eat the '!'.
3538 }
3539
Jim Grosbachd3595712011-08-03 23:50:40 +00003540 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003541 }
Daniel Dunbarf5164f42011-01-18 05:34:24 +00003542
Jim Grosbachd3595712011-08-03 23:50:40 +00003543 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3544 Parser.Lex(); // Eat the comma.
Daniel Dunbarf5164f42011-01-18 05:34:24 +00003545
Jim Grosbacha95ec992011-10-11 17:29:55 +00003546 // If we have a ':', it's an alignment specifier.
3547 if (Parser.getTok().is(AsmToken::Colon)) {
3548 Parser.Lex(); // Eat the ':'.
3549 E = Parser.getTok().getLoc();
3550
3551 const MCExpr *Expr;
3552 if (getParser().ParseExpression(Expr))
3553 return true;
3554
3555 // The expression has to be a constant. Memory references with relocations
3556 // don't come through here, as they use the <label> forms of the relevant
3557 // instructions.
3558 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3559 if (!CE)
3560 return Error (E, "constant expression expected");
3561
3562 unsigned Align = 0;
3563 switch (CE->getValue()) {
3564 default:
3565 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3566 case 64: Align = 8; break;
3567 case 128: Align = 16; break;
3568 case 256: Align = 32; break;
3569 }
3570
3571 // Now we should have the closing ']'
3572 E = Parser.getTok().getLoc();
3573 if (Parser.getTok().isNot(AsmToken::RBrac))
3574 return Error(E, "']' expected");
3575 Parser.Lex(); // Eat right bracket token.
3576
3577 // Don't worry about range checking the value here. That's handled by
3578 // the is*() predicates.
3579 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3580 ARM_AM::no_shift, 0, Align,
3581 false, S, E));
3582
3583 // If there's a pre-indexing writeback marker, '!', just add it as a token
3584 // operand.
3585 if (Parser.getTok().is(AsmToken::Exclaim)) {
3586 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3587 Parser.Lex(); // Eat the '!'.
3588 }
3589
3590 return false;
3591 }
3592
3593 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach8279c182011-11-15 22:14:41 +00003594 // offset. Be friendly and also accept a plain integer (without a leading
3595 // hash) for gas compatibility.
3596 if (Parser.getTok().is(AsmToken::Hash) ||
3597 Parser.getTok().is(AsmToken::Integer)) {
3598 if (Parser.getTok().is(AsmToken::Hash))
3599 Parser.Lex(); // Eat the '#'.
Jim Grosbachd3595712011-08-03 23:50:40 +00003600 E = Parser.getTok().getLoc();
Daniel Dunbarf5164f42011-01-18 05:34:24 +00003601
Owen Anderson967674d2011-08-29 19:36:44 +00003602 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbachd3595712011-08-03 23:50:40 +00003603 const MCExpr *Offset;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003604 if (getParser().ParseExpression(Offset))
3605 return true;
Jim Grosbachd3595712011-08-03 23:50:40 +00003606
3607 // The expression has to be a constant. Memory references with relocations
3608 // don't come through here, as they use the <label> forms of the relevant
3609 // instructions.
3610 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3611 if (!CE)
3612 return Error (E, "constant expression expected");
3613
Owen Anderson967674d2011-08-29 19:36:44 +00003614 // If the constant was #-0, represent it as INT32_MIN.
3615 int32_t Val = CE->getValue();
3616 if (isNegative && Val == 0)
3617 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3618
Jim Grosbachd3595712011-08-03 23:50:40 +00003619 // Now we should have the closing ']'
3620 E = Parser.getTok().getLoc();
3621 if (Parser.getTok().isNot(AsmToken::RBrac))
3622 return Error(E, "']' expected");
3623 Parser.Lex(); // Eat right bracket token.
3624
3625 // Don't worry about range checking the value here. That's handled by
3626 // the is*() predicates.
3627 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbacha95ec992011-10-11 17:29:55 +00003628 ARM_AM::no_shift, 0, 0,
3629 false, S, E));
Jim Grosbachd3595712011-08-03 23:50:40 +00003630
3631 // If there's a pre-indexing writeback marker, '!', just add it as a token
3632 // operand.
3633 if (Parser.getTok().is(AsmToken::Exclaim)) {
3634 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3635 Parser.Lex(); // Eat the '!'.
3636 }
3637
3638 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003639 }
Jim Grosbachd3595712011-08-03 23:50:40 +00003640
3641 // The register offset is optionally preceded by a '+' or '-'
3642 bool isNegative = false;
3643 if (Parser.getTok().is(AsmToken::Minus)) {
3644 isNegative = true;
3645 Parser.Lex(); // Eat the '-'.
3646 } else if (Parser.getTok().is(AsmToken::Plus)) {
3647 // Nothing to do.
3648 Parser.Lex(); // Eat the '+'.
3649 }
3650
3651 E = Parser.getTok().getLoc();
3652 int OffsetRegNum = tryParseRegister();
3653 if (OffsetRegNum == -1)
3654 return Error(E, "register expected");
3655
3656 // If there's a shift operator, handle it.
3657 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00003658 unsigned ShiftImm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00003659 if (Parser.getTok().is(AsmToken::Comma)) {
3660 Parser.Lex(); // Eat the ','.
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00003661 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbachd3595712011-08-03 23:50:40 +00003662 return true;
3663 }
3664
3665 // Now we should have the closing ']'
3666 E = Parser.getTok().getLoc();
3667 if (Parser.getTok().isNot(AsmToken::RBrac))
3668 return Error(E, "']' expected");
3669 Parser.Lex(); // Eat right bracket token.
3670
3671 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbacha95ec992011-10-11 17:29:55 +00003672 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbachd3595712011-08-03 23:50:40 +00003673 S, E));
3674
Jim Grosbachc320c852011-08-05 21:28:30 +00003675 // If there's a pre-indexing writeback marker, '!', just add it as a token
3676 // operand.
3677 if (Parser.getTok().is(AsmToken::Exclaim)) {
3678 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3679 Parser.Lex(); // Eat the '!'.
3680 }
Jim Grosbachd3595712011-08-03 23:50:40 +00003681
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003682 return false;
3683}
3684
Jim Grosbachd3595712011-08-03 23:50:40 +00003685/// parseMemRegOffsetShift - one of these two:
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003686/// ( lsl | lsr | asr | ror ) , # shift_amount
3687/// rrx
Jim Grosbachd3595712011-08-03 23:50:40 +00003688/// return true if it parses a shift otherwise it returns false.
3689bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
3690 unsigned &Amount) {
3691 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan936b0d32010-01-19 21:44:56 +00003692 const AsmToken &Tok = Parser.getTok();
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003693 if (Tok.isNot(AsmToken::Identifier))
3694 return true;
Benjamin Kramer92d89982010-07-14 22:38:02 +00003695 StringRef ShiftName = Tok.getString();
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003696 if (ShiftName == "lsl" || ShiftName == "LSL")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003697 St = ARM_AM::lsl;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003698 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003699 St = ARM_AM::lsr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003700 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003701 St = ARM_AM::asr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003702 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003703 St = ARM_AM::ror;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003704 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003705 St = ARM_AM::rrx;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003706 else
Jim Grosbachd3595712011-08-03 23:50:40 +00003707 return Error(Loc, "illegal shift operator");
Sean Callanana83fd7d2010-01-19 20:27:46 +00003708 Parser.Lex(); // Eat shift type token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003709
Jim Grosbachd3595712011-08-03 23:50:40 +00003710 // rrx stands alone.
3711 Amount = 0;
3712 if (St != ARM_AM::rrx) {
3713 Loc = Parser.getTok().getLoc();
3714 // A '#' and a shift amount.
3715 const AsmToken &HashTok = Parser.getTok();
3716 if (HashTok.isNot(AsmToken::Hash))
3717 return Error(HashTok.getLoc(), "'#' expected");
3718 Parser.Lex(); // Eat hash token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003719
Jim Grosbachd3595712011-08-03 23:50:40 +00003720 const MCExpr *Expr;
3721 if (getParser().ParseExpression(Expr))
3722 return true;
3723 // Range check the immediate.
3724 // lsl, ror: 0 <= imm <= 31
3725 // lsr, asr: 0 <= imm <= 32
3726 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3727 if (!CE)
3728 return Error(Loc, "shift amount must be an immediate");
3729 int64_t Imm = CE->getValue();
3730 if (Imm < 0 ||
3731 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
3732 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
3733 return Error(Loc, "immediate shift value out of range");
3734 Amount = Imm;
3735 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003736
3737 return false;
3738}
3739
Jim Grosbache7fbce72011-10-03 23:38:36 +00003740/// parseFPImm - A floating point immediate expression operand.
3741ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3742parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3743 SMLoc S = Parser.getTok().getLoc();
3744
3745 if (Parser.getTok().isNot(AsmToken::Hash))
3746 return MatchOperand_NoMatch;
Jim Grosbach741cd732011-10-17 22:26:03 +00003747
3748 // Disambiguate the VMOV forms that can accept an FP immediate.
3749 // vmov.f32 <sreg>, #imm
3750 // vmov.f64 <dreg>, #imm
3751 // vmov.f32 <dreg>, #imm @ vector f32x2
3752 // vmov.f32 <qreg>, #imm @ vector f32x4
3753 //
3754 // There are also the NEON VMOV instructions which expect an
3755 // integer constant. Make sure we don't try to parse an FPImm
3756 // for these:
3757 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
3758 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
3759 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
3760 TyOp->getToken() != ".f64"))
3761 return MatchOperand_NoMatch;
3762
Jim Grosbache7fbce72011-10-03 23:38:36 +00003763 Parser.Lex(); // Eat the '#'.
3764
3765 // Handle negation, as that still comes through as a separate token.
3766 bool isNegative = false;
3767 if (Parser.getTok().is(AsmToken::Minus)) {
3768 isNegative = true;
3769 Parser.Lex();
3770 }
3771 const AsmToken &Tok = Parser.getTok();
3772 if (Tok.is(AsmToken::Real)) {
3773 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
3774 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3775 // If we had a '-' in front, toggle the sign bit.
3776 IntVal ^= (uint64_t)isNegative << 63;
3777 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
3778 Parser.Lex(); // Eat the token.
3779 if (Val == -1) {
3780 TokError("floating point value out of range");
3781 return MatchOperand_ParseFail;
3782 }
3783 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3784 return MatchOperand_Success;
3785 }
3786 if (Tok.is(AsmToken::Integer)) {
3787 int64_t Val = Tok.getIntVal();
3788 Parser.Lex(); // Eat the token.
3789 if (Val > 255 || Val < 0) {
3790 TokError("encoded floating point value out of range");
3791 return MatchOperand_ParseFail;
3792 }
3793 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3794 return MatchOperand_Success;
3795 }
3796
3797 TokError("invalid floating point immediate");
3798 return MatchOperand_ParseFail;
3799}
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003800/// Parse a arm instruction operand. For now this parses the operand regardless
3801/// of the mnemonic.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003802bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003803 StringRef Mnemonic) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003804 SMLoc S, E;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003805
3806 // Check if the current operand has a custom associated parser, if so, try to
3807 // custom parse the operand, or fallback to the general approach.
Jim Grosbach861e49c2011-02-12 01:34:40 +00003808 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3809 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003810 return false;
Jim Grosbach861e49c2011-02-12 01:34:40 +00003811 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3812 // there was a match, but an error occurred, in which case, just return that
3813 // the operand parsing failed.
3814 if (ResTy == MatchOperand_ParseFail)
3815 return true;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003816
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003817 switch (getLexer().getKind()) {
Bill Wendlingee7f1f92010-11-06 21:42:12 +00003818 default:
3819 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling2063b842010-11-18 23:43:05 +00003820 return true;
Jim Grosbachbb24c592011-07-13 18:49:30 +00003821 case AsmToken::Identifier: {
Jim Grosbach4ab23b52011-10-03 21:12:43 +00003822 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003823 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling2063b842010-11-18 23:43:05 +00003824 return false;
Jim Grosbach0d6022d2011-07-26 20:41:24 +00003825 int Res = tryParseShiftRegister(Operands);
Jim Grosbachbb24c592011-07-13 18:49:30 +00003826 if (Res == 0) // success
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003827 return false;
Jim Grosbachbb24c592011-07-13 18:49:30 +00003828 else if (Res == -1) // irrecoverable error
3829 return true;
Jim Grosbach4ab23b52011-10-03 21:12:43 +00003830 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
3831 S = Parser.getTok().getLoc();
3832 Parser.Lex();
3833 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
3834 return false;
3835 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00003836
3837 // Fall though for the Identifier case that is not a register or a
3838 // special name.
Jim Grosbachbb24c592011-07-13 18:49:30 +00003839 }
Jim Grosbach4e380352011-10-26 21:14:08 +00003840 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderbyb084be92011-01-13 20:32:36 +00003841 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach5c6b6342011-11-01 22:38:31 +00003842 case AsmToken::String: // quoted label names.
Kevin Enderbyb084be92011-01-13 20:32:36 +00003843 case AsmToken::Dot: { // . as a branch target
Kevin Enderby146dcf22009-10-15 20:48:48 +00003844 // This was not a register so parse other operands that start with an
3845 // identifier (like labels) as expressions and create them as immediates.
3846 const MCExpr *IdVal;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003847 S = Parser.getTok().getLoc();
Kevin Enderby146dcf22009-10-15 20:48:48 +00003848 if (getParser().ParseExpression(IdVal))
Bill Wendling2063b842010-11-18 23:43:05 +00003849 return true;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003850 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling2063b842010-11-18 23:43:05 +00003851 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
3852 return false;
3853 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003854 case AsmToken::LBrac:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003855 return parseMemory(Operands);
Kevin Enderbya2b99102009-10-09 21:12:28 +00003856 case AsmToken::LCurly:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003857 return parseRegisterList(Operands);
Owen Andersonf02d98d2011-08-29 17:17:09 +00003858 case AsmToken::Hash: {
Kevin Enderby3a80dac2009-10-13 23:33:38 +00003859 // #42 -> immediate.
3860 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003861 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00003862 Parser.Lex();
Owen Andersonf02d98d2011-08-29 17:17:09 +00003863 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby146dcf22009-10-15 20:48:48 +00003864 const MCExpr *ImmVal;
3865 if (getParser().ParseExpression(ImmVal))
Bill Wendling2063b842010-11-18 23:43:05 +00003866 return true;
Owen Andersonf02d98d2011-08-29 17:17:09 +00003867 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbach7f1f3bd2011-11-01 22:37:37 +00003868 if (CE) {
3869 int32_t Val = CE->getValue();
3870 if (isNegative && Val == 0)
3871 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Andersonf02d98d2011-08-29 17:17:09 +00003872 }
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003873 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling2063b842010-11-18 23:43:05 +00003874 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
3875 return false;
Owen Andersonf02d98d2011-08-29 17:17:09 +00003876 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00003877 case AsmToken::Colon: {
3878 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng965b3c72011-01-13 07:58:56 +00003879 // FIXME: Check it's an expression prefix,
3880 // e.g. (FOO - :lower16:BAR) isn't legal.
3881 ARMMCExpr::VariantKind RefKind;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003882 if (parsePrefix(RefKind))
Jason W Kim1f7bc072011-01-11 23:53:41 +00003883 return true;
3884
Evan Cheng965b3c72011-01-13 07:58:56 +00003885 const MCExpr *SubExprVal;
3886 if (getParser().ParseExpression(SubExprVal))
Jason W Kim1f7bc072011-01-11 23:53:41 +00003887 return true;
3888
Evan Cheng965b3c72011-01-13 07:58:56 +00003889 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
3890 getContext());
Jason W Kim1f7bc072011-01-11 23:53:41 +00003891 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng965b3c72011-01-13 07:58:56 +00003892 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim1f7bc072011-01-11 23:53:41 +00003893 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003894 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00003895 }
3896}
3897
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003898// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng965b3c72011-01-13 07:58:56 +00003899// :lower16: and :upper16:.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003900bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng965b3c72011-01-13 07:58:56 +00003901 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim1f7bc072011-01-11 23:53:41 +00003902
3903 // :lower16: and :upper16: modifiers
Jason W Kim93229972011-01-13 00:27:00 +00003904 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim1f7bc072011-01-11 23:53:41 +00003905 Parser.Lex(); // Eat ':'
3906
3907 if (getLexer().isNot(AsmToken::Identifier)) {
3908 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
3909 return true;
3910 }
3911
3912 StringRef IDVal = Parser.getTok().getIdentifier();
3913 if (IDVal == "lower16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00003914 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00003915 } else if (IDVal == "upper16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00003916 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00003917 } else {
3918 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
3919 return true;
3920 }
3921 Parser.Lex();
3922
3923 if (getLexer().isNot(AsmToken::Colon)) {
3924 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
3925 return true;
3926 }
3927 Parser.Lex(); // Eat the last ':'
3928 return false;
3929}
3930
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003931/// \brief Given a mnemonic, split out possible predication code and carry
3932/// setting letters to form a canonical mnemonic and flags.
3933//
Daniel Dunbar876bb0182011-01-10 12:24:52 +00003934// FIXME: Would be nice to autogen this.
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003935// FIXME: This is a bit of a maze of special cases.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003936StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00003937 unsigned &PredicationCode,
3938 bool &CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003939 unsigned &ProcessorIMod,
3940 StringRef &ITMask) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003941 PredicationCode = ARMCC::AL;
3942 CarrySetting = false;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003943 ProcessorIMod = 0;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003944
Daniel Dunbar876bb0182011-01-10 12:24:52 +00003945 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003946 //
3947 // FIXME: Would be nice to autogen this.
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00003948 if ((Mnemonic == "movs" && isThumb()) ||
3949 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
3950 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
3951 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
3952 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
3953 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
3954 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
3955 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003956 return Mnemonic;
Daniel Dunbar75d26be2010-08-11 06:37:16 +00003957
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00003958 // First, split out any predication code. Ignore mnemonics we know aren't
3959 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbach8d114902011-07-20 18:20:31 +00003960 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach0c398b92011-07-27 21:58:11 +00003961 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach3636be32011-08-22 23:55:58 +00003962 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbachf6d5d602011-09-01 18:22:13 +00003963 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00003964 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
3965 .Case("eq", ARMCC::EQ)
3966 .Case("ne", ARMCC::NE)
3967 .Case("hs", ARMCC::HS)
3968 .Case("cs", ARMCC::HS)
3969 .Case("lo", ARMCC::LO)
3970 .Case("cc", ARMCC::LO)
3971 .Case("mi", ARMCC::MI)
3972 .Case("pl", ARMCC::PL)
3973 .Case("vs", ARMCC::VS)
3974 .Case("vc", ARMCC::VC)
3975 .Case("hi", ARMCC::HI)
3976 .Case("ls", ARMCC::LS)
3977 .Case("ge", ARMCC::GE)
3978 .Case("lt", ARMCC::LT)
3979 .Case("gt", ARMCC::GT)
3980 .Case("le", ARMCC::LE)
3981 .Case("al", ARMCC::AL)
3982 .Default(~0U);
3983 if (CC != ~0U) {
3984 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
3985 PredicationCode = CC;
3986 }
Bill Wendling193961b2010-10-29 23:50:21 +00003987 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00003988
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003989 // Next, determine if we have a carry setting bit. We explicitly ignore all
3990 // the instructions we know end in 's'.
3991 if (Mnemonic.endswith("s") &&
Jim Grosbachd3e8e292011-08-17 22:49:09 +00003992 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00003993 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
3994 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
3995 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach51726e22011-07-29 20:26:09 +00003996 Mnemonic == "vrsqrts" || Mnemonic == "srs" ||
3997 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003998 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
3999 CarrySetting = true;
4000 }
4001
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004002 // The "cps" instruction can have a interrupt mode operand which is glued into
4003 // the mnemonic. Check if this is the case, split it and parse the imod op
4004 if (Mnemonic.startswith("cps")) {
4005 // Split out any imod code.
4006 unsigned IMod =
4007 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4008 .Case("ie", ARM_PROC::IE)
4009 .Case("id", ARM_PROC::ID)
4010 .Default(~0U);
4011 if (IMod != ~0U) {
4012 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4013 ProcessorIMod = IMod;
4014 }
4015 }
4016
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004017 // The "it" instruction has the condition mask on the end of the mnemonic.
4018 if (Mnemonic.startswith("it")) {
4019 ITMask = Mnemonic.slice(2, Mnemonic.size());
4020 Mnemonic = Mnemonic.slice(0, 2);
4021 }
4022
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004023 return Mnemonic;
4024}
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004025
4026/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4027/// inclusion of carry set or predication code operands.
4028//
4029// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00004030void ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004031getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00004032 bool &CanAcceptPredicationCode) {
Daniel Dunbar09264122011-01-11 19:06:29 +00004033 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4034 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00004035 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00004036 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004037 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00004038 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004039 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00004040 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004041 Mnemonic == "mla" || Mnemonic == "smlal" ||
4042 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbar09264122011-01-11 19:06:29 +00004043 CanAcceptCarrySet = true;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004044 } else
Daniel Dunbar09264122011-01-11 19:06:29 +00004045 CanAcceptCarrySet = false;
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004046
Daniel Dunbar09264122011-01-11 19:06:29 +00004047 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4048 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4049 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4050 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbach803898f2011-09-06 20:27:04 +00004051 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4052 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach25977222011-08-19 23:24:36 +00004053 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach93981412011-10-11 21:55:36 +00004054 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4055 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4056 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbachb9d4e372011-08-26 22:21:51 +00004057 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4058 !isThumb()) ||
Jim Grosbachb908b7a2011-09-10 00:15:36 +00004059 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004060 CanAcceptPredicationCode = false;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004061 } else
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004062 CanAcceptPredicationCode = true;
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004063
Jim Grosbach6c45b752011-09-16 16:39:25 +00004064 if (isThumb()) {
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004065 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbachb98ab912011-06-30 22:10:46 +00004066 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004067 CanAcceptPredicationCode = false;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004068 }
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004069}
4070
Jim Grosbach7283da92011-08-16 21:12:37 +00004071bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4072 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004073 // FIXME: This is all horribly hacky. We really need a better way to deal
4074 // with optional operands like this in the matcher table.
Jim Grosbach7283da92011-08-16 21:12:37 +00004075
4076 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4077 // another does not. Specifically, the MOVW instruction does not. So we
4078 // special case it here and remove the defaulted (non-setting) cc_out
4079 // operand if that's the instruction we're trying to match.
4080 //
4081 // We do this as post-processing of the explicit operands rather than just
4082 // conditionally adding the cc_out in the first place because we need
4083 // to check the type of the parsed immediate operand.
Owen Andersond7791b92011-09-14 22:46:14 +00004084 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbach7283da92011-08-16 21:12:37 +00004085 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4086 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4087 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4088 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00004089
4090 // Register-register 'add' for thumb does not have a cc_out operand
4091 // when there are only two register operands.
4092 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4093 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4094 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4095 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4096 return true;
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004097 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004098 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4099 // have to check the immediate range here since Thumb2 has a variant
4100 // that can handle a different range and has a cc_out operand.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004101 if (((isThumb() && Mnemonic == "add") ||
4102 (isThumbTwo() && Mnemonic == "sub")) &&
4103 Operands.size() == 6 &&
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004104 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4105 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4106 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004107 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4108 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4109 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004110 return true;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004111 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4112 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004113 // selecting via the generic "add" mnemonic, so to know that we
4114 // should remove the cc_out operand, we have to explicitly check that
4115 // it's not one of the other variants. Ugh.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004116 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4117 Operands.size() == 6 &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004118 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4119 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4120 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4121 // Nest conditions rather than one big 'if' statement for readability.
4122 //
4123 // If either register is a high reg, it's either one of the SP
4124 // variants (handled above) or a 32-bit encoding, so we just
4125 // check against T3.
4126 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4127 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4128 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4129 return false;
4130 // If both registers are low, we're in an IT block, and the immediate is
4131 // in range, we should use encoding T1 instead, which has a cc_out.
4132 if (inITBlock() &&
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004133 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004134 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4135 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4136 return false;
4137
4138 // Otherwise, we use encoding T4, which does not have a cc_out
4139 // operand.
4140 return true;
4141 }
4142
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004143 // The thumb2 multiply instruction doesn't have a CCOut register, so
4144 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4145 // use the 16-bit encoding or not.
4146 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4147 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4148 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4149 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4150 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4151 // If the registers aren't low regs, the destination reg isn't the
4152 // same as one of the source regs, or the cc_out operand is zero
4153 // outside of an IT block, we have to use the 32-bit encoding, so
4154 // remove the cc_out operand.
4155 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4156 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach6efa7b92011-11-15 19:29:45 +00004157 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004158 !inITBlock() ||
4159 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4160 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4161 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4162 static_cast<ARMOperand*>(Operands[4])->getReg())))
4163 return true;
4164
Jim Grosbachefa7e952011-11-15 19:55:16 +00004165 // Also check the 'mul' syntax variant that doesn't specify an explicit
4166 // destination register.
4167 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4168 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4169 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4170 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4171 // If the registers aren't low regs or the cc_out operand is zero
4172 // outside of an IT block, we have to use the 32-bit encoding, so
4173 // remove the cc_out operand.
4174 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4175 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4176 !inITBlock()))
4177 return true;
4178
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004179
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004180
Jim Grosbach4b701af2011-08-24 21:42:27 +00004181 // Register-register 'add/sub' for thumb does not have a cc_out operand
4182 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4183 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4184 // right, this will result in better diagnostics (which operand is off)
4185 // anyway.
4186 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4187 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004188 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4189 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4190 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4191 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00004192
Jim Grosbach7283da92011-08-16 21:12:37 +00004193 return false;
4194}
4195
Jim Grosbach12952fe2011-11-11 23:08:10 +00004196static bool isDataTypeToken(StringRef Tok) {
4197 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4198 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4199 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4200 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4201 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4202 Tok == ".f" || Tok == ".d";
4203}
4204
4205// FIXME: This bit should probably be handled via an explicit match class
4206// in the .td files that matches the suffix instead of having it be
4207// a literal string token the way it is now.
4208static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4209 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4210}
4211
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004212/// Parse an arm instruction mnemonic followed by its operands.
4213bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4214 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4215 // Create the leading tokens for the mnemonic, split by '.' characters.
4216 size_t Start = 0, Next = Name.find('.');
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004217 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004218
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004219 // Split out the predication code and carry setting flag from the mnemonic.
4220 unsigned PredicationCode;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004221 unsigned ProcessorIMod;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004222 bool CarrySetting;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004223 StringRef ITMask;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004224 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004225 ProcessorIMod, ITMask);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004226
Jim Grosbach1c171b12011-08-25 17:23:55 +00004227 // In Thumb1, only the branch (B) instruction can be predicated.
4228 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4229 Parser.EatToEndOfStatement();
4230 return Error(NameLoc, "conditional execution not supported in Thumb1");
4231 }
4232
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004233 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4234
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004235 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4236 // is the mask as it will be for the IT encoding if the conditional
4237 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4238 // where the conditional bit0 is zero, the instruction post-processing
4239 // will adjust the mask accordingly.
4240 if (Mnemonic == "it") {
Jim Grosbached16ec42011-08-29 22:24:09 +00004241 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4242 if (ITMask.size() > 3) {
4243 Parser.EatToEndOfStatement();
4244 return Error(Loc, "too many conditions on IT instruction");
4245 }
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004246 unsigned Mask = 8;
4247 for (unsigned i = ITMask.size(); i != 0; --i) {
4248 char pos = ITMask[i - 1];
4249 if (pos != 't' && pos != 'e') {
4250 Parser.EatToEndOfStatement();
Jim Grosbached16ec42011-08-29 22:24:09 +00004251 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004252 }
4253 Mask >>= 1;
4254 if (ITMask[i - 1] == 't')
4255 Mask |= 8;
4256 }
Jim Grosbached16ec42011-08-29 22:24:09 +00004257 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004258 }
4259
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004260 // FIXME: This is all a pretty gross hack. We should automatically handle
4261 // optional operands like this via tblgen.
Bill Wendling219dabd2010-11-21 10:56:05 +00004262
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004263 // Next, add the CCOut and ConditionCode operands, if needed.
4264 //
4265 // For mnemonics which can ever incorporate a carry setting bit or predication
4266 // code, our matching model involves us always generating CCOut and
4267 // ConditionCode operands to match the mnemonic "as written" and then we let
4268 // the matcher deal with finding the right instruction or generating an
4269 // appropriate error.
4270 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004271 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004272
Jim Grosbach03a8a162011-07-14 22:04:21 +00004273 // If we had a carry-set on an instruction that can't do that, issue an
4274 // error.
4275 if (!CanAcceptCarrySet && CarrySetting) {
4276 Parser.EatToEndOfStatement();
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004277 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach03a8a162011-07-14 22:04:21 +00004278 "' can not set flags, but 's' suffix specified");
4279 }
Jim Grosbach0a547702011-07-22 17:44:50 +00004280 // If we had a predication code on an instruction that can't do that, issue an
4281 // error.
4282 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4283 Parser.EatToEndOfStatement();
4284 return Error(NameLoc, "instruction '" + Mnemonic +
4285 "' is not predicable, but condition code specified");
4286 }
Jim Grosbach03a8a162011-07-14 22:04:21 +00004287
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004288 // Add the carry setting operand, if necessary.
Jim Grosbached16ec42011-08-29 22:24:09 +00004289 if (CanAcceptCarrySet) {
4290 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004291 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbached16ec42011-08-29 22:24:09 +00004292 Loc));
4293 }
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004294
4295 // Add the predication code operand, if necessary.
4296 if (CanAcceptPredicationCode) {
Jim Grosbached16ec42011-08-29 22:24:09 +00004297 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4298 CarrySetting);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004299 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbached16ec42011-08-29 22:24:09 +00004300 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004301 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004302
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004303 // Add the processor imod operand, if necessary.
4304 if (ProcessorIMod) {
4305 Operands.push_back(ARMOperand::CreateImm(
4306 MCConstantExpr::Create(ProcessorIMod, getContext()),
4307 NameLoc, NameLoc));
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004308 }
4309
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004310 // Add the remaining tokens in the mnemonic.
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004311 while (Next != StringRef::npos) {
4312 Start = Next;
4313 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004314 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004315
Jim Grosbach12952fe2011-11-11 23:08:10 +00004316 // Some NEON instructions have an optional datatype suffix that is
4317 // completely ignored. Check for that.
4318 if (isDataTypeToken(ExtraToken) &&
4319 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4320 continue;
4321
Jim Grosbach39c6e1d2011-09-07 16:06:04 +00004322 if (ExtraToken != ".n") {
4323 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4324 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4325 }
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004326 }
4327
4328 // Read the remaining operands.
4329 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004330 // Read the first operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004331 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnera2a9d162010-09-11 16:18:25 +00004332 Parser.EatToEndOfStatement();
4333 return true;
4334 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004335
4336 while (getLexer().is(AsmToken::Comma)) {
Sean Callanana83fd7d2010-01-19 20:27:46 +00004337 Parser.Lex(); // Eat the comma.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004338
4339 // Parse and remember the operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004340 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnera2a9d162010-09-11 16:18:25 +00004341 Parser.EatToEndOfStatement();
4342 return true;
4343 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004344 }
4345 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00004346
Chris Lattnera2a9d162010-09-11 16:18:25 +00004347 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbachb8d9f512011-10-07 18:27:04 +00004348 SMLoc Loc = getLexer().getLoc();
Chris Lattnera2a9d162010-09-11 16:18:25 +00004349 Parser.EatToEndOfStatement();
Jim Grosbachb8d9f512011-10-07 18:27:04 +00004350 return Error(Loc, "unexpected token in argument list");
Chris Lattnera2a9d162010-09-11 16:18:25 +00004351 }
Bill Wendlingee7f1f92010-11-06 21:42:12 +00004352
Chris Lattner91689c12010-09-08 05:10:46 +00004353 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004354
Jim Grosbach7283da92011-08-16 21:12:37 +00004355 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4356 // do and don't have a cc_out optional-def operand. With some spot-checks
4357 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004358 // parse and adjust accordingly before actually matching. We shouldn't ever
4359 // try to remove a cc_out operand that was explicitly set on the the
4360 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4361 // table driven matcher doesn't fit well with the ARM instruction set.
4362 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004363 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4364 Operands.erase(Operands.begin() + 1);
4365 delete Op;
4366 }
4367
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00004368 // ARM mode 'blx' need special handling, as the register operand version
4369 // is predicable, but the label operand version is not. So, we can't rely
4370 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach6e5778f2011-10-07 23:24:09 +00004371 // a k_CondCode operand in the list. If we're trying to match the label
4372 // version, remove the k_CondCode operand here.
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00004373 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4374 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4375 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4376 Operands.erase(Operands.begin() + 1);
4377 delete Op;
4378 }
Jim Grosbach8cffa282011-08-11 23:51:13 +00004379
4380 // The vector-compare-to-zero instructions have a literal token "#0" at
4381 // the end that comes to here as an immediate operand. Convert it to a
4382 // token to play nicely with the matcher.
4383 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4384 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4385 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4386 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4387 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4388 if (CE && CE->getValue() == 0) {
4389 Operands.erase(Operands.begin() + 5);
4390 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4391 delete Op;
4392 }
4393 }
Jim Grosbach46b66462011-10-03 22:30:24 +00004394 // VCMP{E} does the same thing, but with a different operand count.
4395 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4396 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4397 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4398 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4399 if (CE && CE->getValue() == 0) {
4400 Operands.erase(Operands.begin() + 4);
4401 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4402 delete Op;
4403 }
4404 }
Jim Grosbachc3c32d92011-08-22 23:47:13 +00004405 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
4406 // end. Convert it to a token here.
4407 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
4408 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4409 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4410 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4411 if (CE && CE->getValue() == 0) {
4412 Operands.erase(Operands.begin() + 5);
4413 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4414 delete Op;
4415 }
4416 }
4417
Chris Lattnerf29c0b62010-01-14 22:21:20 +00004418 return false;
Kevin Enderbyccab3172009-09-15 00:27:25 +00004419}
4420
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004421// Validate context-sensitive operand constraints.
Jim Grosbach169b2be2011-08-23 18:13:04 +00004422
4423// return 'true' if register list contains non-low GPR registers,
4424// 'false' otherwise. If Reg is in the register list or is HiReg, set
4425// 'containsReg' to true.
4426static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4427 unsigned HiReg, bool &containsReg) {
4428 containsReg = false;
4429 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4430 unsigned OpReg = Inst.getOperand(i).getReg();
4431 if (OpReg == Reg)
4432 containsReg = true;
4433 // Anything other than a low register isn't legal here.
4434 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4435 return true;
4436 }
4437 return false;
4438}
4439
Jim Grosbacha31f2232011-09-07 18:05:34 +00004440// Check if the specified regisgter is in the register list of the inst,
4441// starting at the indicated operand number.
4442static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4443 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4444 unsigned OpReg = Inst.getOperand(i).getReg();
4445 if (OpReg == Reg)
4446 return true;
4447 }
4448 return false;
4449}
4450
Jim Grosbached16ec42011-08-29 22:24:09 +00004451// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4452// the ARMInsts array) instead. Getting that here requires awkward
4453// API changes, though. Better way?
4454namespace llvm {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00004455extern const MCInstrDesc ARMInsts[];
Jim Grosbached16ec42011-08-29 22:24:09 +00004456}
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00004457static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbached16ec42011-08-29 22:24:09 +00004458 return ARMInsts[Opcode];
4459}
4460
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004461// FIXME: We would really like to be able to tablegen'erate this.
4462bool ARMAsmParser::
4463validateInstruction(MCInst &Inst,
4464 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00004465 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbached16ec42011-08-29 22:24:09 +00004466 SMLoc Loc = Operands[0]->getStartLoc();
4467 // Check the IT block state first.
Owen Anderson44ae2da2011-09-13 17:59:19 +00004468 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4469 // being allowed in IT blocks, but not being predicable. It just always
4470 // executes.
4471 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbached16ec42011-08-29 22:24:09 +00004472 unsigned bit = 1;
4473 if (ITState.FirstCond)
4474 ITState.FirstCond = false;
4475 else
Jim Grosbacha0d34d32011-09-02 23:22:08 +00004476 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbached16ec42011-08-29 22:24:09 +00004477 // The instruction must be predicable.
4478 if (!MCID.isPredicable())
4479 return Error(Loc, "instructions in IT block must be predicable");
4480 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4481 unsigned ITCond = bit ? ITState.Cond :
4482 ARMCC::getOppositeCondition(ITState.Cond);
4483 if (Cond != ITCond) {
4484 // Find the condition code Operand to get its SMLoc information.
4485 SMLoc CondLoc;
4486 for (unsigned i = 1; i < Operands.size(); ++i)
4487 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4488 CondLoc = Operands[i]->getStartLoc();
4489 return Error(CondLoc, "incorrect condition in IT block; got '" +
4490 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4491 "', but expected '" +
4492 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4493 }
Jim Grosbachc61fc8f2011-08-31 18:29:05 +00004494 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00004495 } else if (isThumbTwo() && MCID.isPredicable() &&
4496 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson29cfe6c2011-09-09 21:48:23 +00004497 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4498 Inst.getOpcode() != ARM::t2B)
Jim Grosbached16ec42011-08-29 22:24:09 +00004499 return Error(Loc, "predicated instructions must be in IT block");
4500
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004501 switch (Inst.getOpcode()) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00004502 case ARM::LDRD:
4503 case ARM::LDRD_PRE:
4504 case ARM::LDRD_POST:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004505 case ARM::LDREXD: {
4506 // Rt2 must be Rt + 1.
4507 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4508 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4509 if (Rt2 != Rt + 1)
4510 return Error(Operands[3]->getStartLoc(),
4511 "destination operands must be sequential");
4512 return false;
4513 }
Jim Grosbacheb09f492011-08-11 20:28:23 +00004514 case ARM::STRD: {
4515 // Rt2 must be Rt + 1.
4516 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4517 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4518 if (Rt2 != Rt + 1)
4519 return Error(Operands[3]->getStartLoc(),
4520 "source operands must be sequential");
4521 return false;
4522 }
Jim Grosbachf7164b22011-08-10 20:49:18 +00004523 case ARM::STRD_PRE:
4524 case ARM::STRD_POST:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004525 case ARM::STREXD: {
4526 // Rt2 must be Rt + 1.
4527 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4528 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
4529 if (Rt2 != Rt + 1)
Jim Grosbacheb09f492011-08-11 20:28:23 +00004530 return Error(Operands[3]->getStartLoc(),
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004531 "source operands must be sequential");
4532 return false;
4533 }
Jim Grosbach03f56d92011-07-27 21:09:25 +00004534 case ARM::SBFX:
4535 case ARM::UBFX: {
4536 // width must be in range [1, 32-lsb]
4537 unsigned lsb = Inst.getOperand(2).getImm();
4538 unsigned widthm1 = Inst.getOperand(3).getImm();
4539 if (widthm1 >= 32 - lsb)
4540 return Error(Operands[5]->getStartLoc(),
4541 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach64610e52011-08-16 21:42:31 +00004542 return false;
Jim Grosbach03f56d92011-07-27 21:09:25 +00004543 }
Jim Grosbach90103cc2011-08-18 21:50:53 +00004544 case ARM::tLDMIA: {
Jim Grosbacha31f2232011-09-07 18:05:34 +00004545 // If we're parsing Thumb2, the .w variant is available and handles
4546 // most cases that are normally illegal for a Thumb1 LDM
4547 // instruction. We'll make the transformation in processInstruction()
4548 // if necessary.
4549 //
Jim Grosbach90103cc2011-08-18 21:50:53 +00004550 // Thumb LDM instructions are writeback iff the base register is not
4551 // in the register list.
4552 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach139acd22011-08-22 23:01:07 +00004553 bool hasWritebackToken =
4554 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4555 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbach169b2be2011-08-23 18:13:04 +00004556 bool listContainsBase;
Jim Grosbacha31f2232011-09-07 18:05:34 +00004557 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00004558 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4559 "registers must be in range r0-r7");
Jim Grosbach90103cc2011-08-18 21:50:53 +00004560 // If we should have writeback, then there should be a '!' token.
Jim Grosbacha31f2232011-09-07 18:05:34 +00004561 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach90103cc2011-08-18 21:50:53 +00004562 return Error(Operands[2]->getStartLoc(),
4563 "writeback operator '!' expected");
Jim Grosbacha31f2232011-09-07 18:05:34 +00004564 // If we should not have writeback, there must not be a '!'. This is
4565 // true even for the 32-bit wide encodings.
Jim Grosbach169b2be2011-08-23 18:13:04 +00004566 if (listContainsBase && hasWritebackToken)
Jim Grosbach139acd22011-08-22 23:01:07 +00004567 return Error(Operands[3]->getStartLoc(),
4568 "writeback operator '!' not allowed when base register "
4569 "in register list");
Jim Grosbach90103cc2011-08-18 21:50:53 +00004570
4571 break;
4572 }
Jim Grosbacha31f2232011-09-07 18:05:34 +00004573 case ARM::t2LDMIA_UPD: {
4574 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
4575 return Error(Operands[4]->getStartLoc(),
4576 "writeback operator '!' not allowed when base register "
4577 "in register list");
4578 break;
4579 }
Jim Grosbach9bded9d2011-11-10 23:17:11 +00004580 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
4581 // so only issue a diagnostic for thumb1. The instructions will be
4582 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach38c59fc2011-08-22 23:17:34 +00004583 case ARM::tPOP: {
Jim Grosbach169b2be2011-08-23 18:13:04 +00004584 bool listContainsBase;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00004585 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
4586 !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00004587 return Error(Operands[2]->getStartLoc(),
4588 "registers must be in range r0-r7 or pc");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00004589 break;
4590 }
4591 case ARM::tPUSH: {
Jim Grosbach169b2be2011-08-23 18:13:04 +00004592 bool listContainsBase;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00004593 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
4594 !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00004595 return Error(Operands[2]->getStartLoc(),
4596 "registers must be in range r0-r7 or lr");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00004597 break;
4598 }
Jim Grosbachd80d1692011-08-23 18:15:37 +00004599 case ARM::tSTMIA_UPD: {
4600 bool listContainsBase;
Jim Grosbach099c9762011-09-16 20:50:13 +00004601 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachd80d1692011-08-23 18:15:37 +00004602 return Error(Operands[4]->getStartLoc(),
4603 "registers must be in range r0-r7");
4604 break;
4605 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004606 }
4607
4608 return false;
4609}
4610
Jim Grosbachafad0532011-11-10 23:42:14 +00004611bool ARMAsmParser::
Jim Grosbach8ba76c62011-08-11 17:35:48 +00004612processInstruction(MCInst &Inst,
4613 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4614 switch (Inst.getOpcode()) {
Jim Grosbach61db5a52011-11-10 16:44:55 +00004615 // Handle the MOV complex aliases.
Jim Grosbachabcac562011-11-16 18:31:45 +00004616 case ARM::ASRr:
4617 case ARM::LSRr:
4618 case ARM::LSLr:
4619 case ARM::RORr: {
4620 ARM_AM::ShiftOpc ShiftTy;
4621 switch(Inst.getOpcode()) {
4622 default: llvm_unreachable("unexpected opcode!");
4623 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
4624 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
4625 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
4626 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
4627 }
4628 // A shift by zero is a plain MOVr, not a MOVsi.
4629 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
4630 MCInst TmpInst;
4631 TmpInst.setOpcode(ARM::MOVsr);
4632 TmpInst.addOperand(Inst.getOperand(0)); // Rd
4633 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4634 TmpInst.addOperand(Inst.getOperand(2)); // Rm
4635 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
4636 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
4637 TmpInst.addOperand(Inst.getOperand(4));
4638 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
4639 Inst = TmpInst;
4640 return true;
4641 }
Jim Grosbachc14871c2011-11-10 19:18:01 +00004642 case ARM::ASRi:
4643 case ARM::LSRi:
4644 case ARM::LSLi:
4645 case ARM::RORi: {
4646 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachc14871c2011-11-10 19:18:01 +00004647 switch(Inst.getOpcode()) {
4648 default: llvm_unreachable("unexpected opcode!");
4649 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
4650 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
4651 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
4652 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
4653 }
4654 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach1a2f9ee2011-11-16 19:05:59 +00004655 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachc14871c2011-11-10 19:18:01 +00004656 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
4657 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach61db5a52011-11-10 16:44:55 +00004658 MCInst TmpInst;
Jim Grosbachc14871c2011-11-10 19:18:01 +00004659 TmpInst.setOpcode(Opc);
Jim Grosbach61db5a52011-11-10 16:44:55 +00004660 TmpInst.addOperand(Inst.getOperand(0)); // Rd
4661 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachc14871c2011-11-10 19:18:01 +00004662 if (Opc == ARM::MOVsi)
4663 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach61db5a52011-11-10 16:44:55 +00004664 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
4665 TmpInst.addOperand(Inst.getOperand(4));
4666 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
4667 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00004668 return true;
Jim Grosbach61db5a52011-11-10 16:44:55 +00004669 }
Jim Grosbach1a2f9ee2011-11-16 19:05:59 +00004670 case ARM::RRXi: {
4671 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
4672 MCInst TmpInst;
4673 TmpInst.setOpcode(ARM::MOVsi);
4674 TmpInst.addOperand(Inst.getOperand(0)); // Rd
4675 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4676 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
4677 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4678 TmpInst.addOperand(Inst.getOperand(3));
4679 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
4680 Inst = TmpInst;
4681 return true;
4682 }
Jim Grosbachd9a9be22011-11-10 23:58:34 +00004683 case ARM::t2LDMIA_UPD: {
4684 // If this is a load of a single register, then we should use
4685 // a post-indexed LDR instruction instead, per the ARM ARM.
4686 if (Inst.getNumOperands() != 5)
4687 return false;
4688 MCInst TmpInst;
4689 TmpInst.setOpcode(ARM::t2LDR_POST);
4690 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4691 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4692 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4693 TmpInst.addOperand(MCOperand::CreateImm(4));
4694 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4695 TmpInst.addOperand(Inst.getOperand(3));
4696 Inst = TmpInst;
4697 return true;
4698 }
4699 case ARM::t2STMDB_UPD: {
4700 // If this is a store of a single register, then we should use
4701 // a pre-indexed STR instruction instead, per the ARM ARM.
4702 if (Inst.getNumOperands() != 5)
4703 return false;
4704 MCInst TmpInst;
4705 TmpInst.setOpcode(ARM::t2STR_PRE);
4706 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4707 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4708 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4709 TmpInst.addOperand(MCOperand::CreateImm(-4));
4710 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4711 TmpInst.addOperand(Inst.getOperand(3));
4712 Inst = TmpInst;
4713 return true;
4714 }
Jim Grosbach8ba76c62011-08-11 17:35:48 +00004715 case ARM::LDMIA_UPD:
4716 // If this is a load of a single register via a 'pop', then we should use
4717 // a post-indexed LDR instruction instead, per the ARM ARM.
4718 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
4719 Inst.getNumOperands() == 5) {
4720 MCInst TmpInst;
4721 TmpInst.setOpcode(ARM::LDR_POST_IMM);
4722 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4723 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4724 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4725 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
4726 TmpInst.addOperand(MCOperand::CreateImm(4));
4727 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4728 TmpInst.addOperand(Inst.getOperand(3));
4729 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00004730 return true;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00004731 }
4732 break;
Jim Grosbach27ad83d2011-08-11 18:07:11 +00004733 case ARM::STMDB_UPD:
4734 // If this is a store of a single register via a 'push', then we should use
4735 // a pre-indexed STR instruction instead, per the ARM ARM.
4736 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
4737 Inst.getNumOperands() == 5) {
4738 MCInst TmpInst;
4739 TmpInst.setOpcode(ARM::STR_PRE_IMM);
4740 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4741 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4742 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
4743 TmpInst.addOperand(MCOperand::CreateImm(-4));
4744 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4745 TmpInst.addOperand(Inst.getOperand(3));
4746 Inst = TmpInst;
4747 }
4748 break;
Jim Grosbache9ab47a2011-08-16 23:57:34 +00004749 case ARM::tADDi8:
Jim Grosbach6d606fb2011-08-31 17:07:33 +00004750 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4751 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4752 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4753 // to encoding T1 if <Rd> is omitted."
Jim Grosbachafad0532011-11-10 23:42:14 +00004754 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbache9ab47a2011-08-16 23:57:34 +00004755 Inst.setOpcode(ARM::tADDi3);
Jim Grosbachafad0532011-11-10 23:42:14 +00004756 return true;
4757 }
Jim Grosbache9ab47a2011-08-16 23:57:34 +00004758 break;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004759 case ARM::tSUBi8:
4760 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4761 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4762 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4763 // to encoding T1 if <Rd> is omitted."
Jim Grosbachafad0532011-11-10 23:42:14 +00004764 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004765 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbachafad0532011-11-10 23:42:14 +00004766 return true;
4767 }
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004768 break;
Owen Anderson29cfe6c2011-09-09 21:48:23 +00004769 case ARM::tB:
4770 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbachafad0532011-11-10 23:42:14 +00004771 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson29cfe6c2011-09-09 21:48:23 +00004772 Inst.setOpcode(ARM::tBcc);
Jim Grosbachafad0532011-11-10 23:42:14 +00004773 return true;
4774 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00004775 break;
4776 case ARM::t2B:
4777 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbachafad0532011-11-10 23:42:14 +00004778 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson29cfe6c2011-09-09 21:48:23 +00004779 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbachafad0532011-11-10 23:42:14 +00004780 return true;
4781 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00004782 break;
Jim Grosbach99bc8462011-08-31 21:17:31 +00004783 case ARM::t2Bcc:
Jim Grosbacha0d34d32011-09-02 23:22:08 +00004784 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbachafad0532011-11-10 23:42:14 +00004785 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbach99bc8462011-08-31 21:17:31 +00004786 Inst.setOpcode(ARM::t2B);
Jim Grosbachafad0532011-11-10 23:42:14 +00004787 return true;
4788 }
Jim Grosbach99bc8462011-08-31 21:17:31 +00004789 break;
Jim Grosbachcbd4ab12011-08-17 22:57:40 +00004790 case ARM::tBcc:
4791 // If the conditional is AL, we really want tB.
Jim Grosbachafad0532011-11-10 23:42:14 +00004792 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbachcbd4ab12011-08-17 22:57:40 +00004793 Inst.setOpcode(ARM::tB);
Jim Grosbachafad0532011-11-10 23:42:14 +00004794 return true;
4795 }
Jim Grosbach6ddb5682011-08-18 16:08:39 +00004796 break;
Jim Grosbacha31f2232011-09-07 18:05:34 +00004797 case ARM::tLDMIA: {
4798 // If the register list contains any high registers, or if the writeback
4799 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
4800 // instead if we're in Thumb2. Otherwise, this should have generated
4801 // an error in validateInstruction().
4802 unsigned Rn = Inst.getOperand(0).getReg();
4803 bool hasWritebackToken =
4804 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4805 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
4806 bool listContainsBase;
4807 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
4808 (!listContainsBase && !hasWritebackToken) ||
4809 (listContainsBase && hasWritebackToken)) {
4810 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4811 assert (isThumbTwo());
4812 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
4813 // If we're switching to the updating version, we need to insert
4814 // the writeback tied operand.
4815 if (hasWritebackToken)
4816 Inst.insert(Inst.begin(),
4817 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbachafad0532011-11-10 23:42:14 +00004818 return true;
Jim Grosbacha31f2232011-09-07 18:05:34 +00004819 }
4820 break;
4821 }
Jim Grosbach099c9762011-09-16 20:50:13 +00004822 case ARM::tSTMIA_UPD: {
4823 // If the register list contains any high registers, we need to use
4824 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
4825 // should have generated an error in validateInstruction().
4826 unsigned Rn = Inst.getOperand(0).getReg();
4827 bool listContainsBase;
4828 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
4829 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4830 assert (isThumbTwo());
4831 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbachafad0532011-11-10 23:42:14 +00004832 return true;
Jim Grosbach099c9762011-09-16 20:50:13 +00004833 }
4834 break;
4835 }
Jim Grosbach9bded9d2011-11-10 23:17:11 +00004836 case ARM::tPOP: {
4837 bool listContainsBase;
4838 // If the register list contains any high registers, we need to use
4839 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
4840 // should have generated an error in validateInstruction().
4841 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbachafad0532011-11-10 23:42:14 +00004842 return false;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00004843 assert (isThumbTwo());
4844 Inst.setOpcode(ARM::t2LDMIA_UPD);
4845 // Add the base register and writeback operands.
4846 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
4847 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbachafad0532011-11-10 23:42:14 +00004848 return true;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00004849 }
4850 case ARM::tPUSH: {
4851 bool listContainsBase;
4852 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbachafad0532011-11-10 23:42:14 +00004853 return false;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00004854 assert (isThumbTwo());
4855 Inst.setOpcode(ARM::t2STMDB_UPD);
4856 // Add the base register and writeback operands.
4857 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
4858 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbachafad0532011-11-10 23:42:14 +00004859 return true;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00004860 }
Jim Grosbachb908b7a2011-09-10 00:15:36 +00004861 case ARM::t2MOVi: {
4862 // If we can use the 16-bit encoding and the user didn't explicitly
4863 // request the 32-bit variant, transform it here.
4864 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4865 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbach18b8b172011-09-14 19:12:11 +00004866 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
4867 Inst.getOperand(4).getReg() == ARM::CPSR) ||
4868 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbachb908b7a2011-09-10 00:15:36 +00004869 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4870 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4871 // The operands aren't in the same order for tMOVi8...
4872 MCInst TmpInst;
4873 TmpInst.setOpcode(ARM::tMOVi8);
4874 TmpInst.addOperand(Inst.getOperand(0));
4875 TmpInst.addOperand(Inst.getOperand(4));
4876 TmpInst.addOperand(Inst.getOperand(1));
4877 TmpInst.addOperand(Inst.getOperand(2));
4878 TmpInst.addOperand(Inst.getOperand(3));
4879 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00004880 return true;
Jim Grosbachb908b7a2011-09-10 00:15:36 +00004881 }
4882 break;
4883 }
4884 case ARM::t2MOVr: {
4885 // If we can use the 16-bit encoding and the user didn't explicitly
4886 // request the 32-bit variant, transform it here.
4887 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4888 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4889 Inst.getOperand(2).getImm() == ARMCC::AL &&
4890 Inst.getOperand(4).getReg() == ARM::CPSR &&
4891 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4892 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4893 // The operands aren't the same for tMOV[S]r... (no cc_out)
4894 MCInst TmpInst;
4895 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
4896 TmpInst.addOperand(Inst.getOperand(0));
4897 TmpInst.addOperand(Inst.getOperand(1));
4898 TmpInst.addOperand(Inst.getOperand(2));
4899 TmpInst.addOperand(Inst.getOperand(3));
4900 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00004901 return true;
Jim Grosbachb908b7a2011-09-10 00:15:36 +00004902 }
4903 break;
4904 }
Jim Grosbach82213192011-09-19 20:29:33 +00004905 case ARM::t2SXTH:
Jim Grosbachb3519802011-09-20 00:46:54 +00004906 case ARM::t2SXTB:
4907 case ARM::t2UXTH:
4908 case ARM::t2UXTB: {
Jim Grosbach82213192011-09-19 20:29:33 +00004909 // If we can use the 16-bit encoding and the user didn't explicitly
4910 // request the 32-bit variant, transform it here.
4911 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4912 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4913 Inst.getOperand(2).getImm() == 0 &&
4914 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4915 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbachb3519802011-09-20 00:46:54 +00004916 unsigned NewOpc;
4917 switch (Inst.getOpcode()) {
4918 default: llvm_unreachable("Illegal opcode!");
4919 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
4920 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
4921 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
4922 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
4923 }
Jim Grosbach82213192011-09-19 20:29:33 +00004924 // The operands aren't the same for thumb1 (no rotate operand).
4925 MCInst TmpInst;
4926 TmpInst.setOpcode(NewOpc);
4927 TmpInst.addOperand(Inst.getOperand(0));
4928 TmpInst.addOperand(Inst.getOperand(1));
4929 TmpInst.addOperand(Inst.getOperand(3));
4930 TmpInst.addOperand(Inst.getOperand(4));
4931 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00004932 return true;
Jim Grosbach82213192011-09-19 20:29:33 +00004933 }
4934 break;
4935 }
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004936 case ARM::t2IT: {
4937 // The mask bits for all but the first condition are represented as
4938 // the low bit of the condition code value implies 't'. We currently
4939 // always have 1 implies 't', so XOR toggle the bits if the low bit
4940 // of the condition code is zero. The encoding also expects the low
4941 // bit of the condition to be encoded as bit 4 of the mask operand,
4942 // so mask that in if needed
4943 MCOperand &MO = Inst.getOperand(1);
4944 unsigned Mask = MO.getImm();
Jim Grosbached16ec42011-08-29 22:24:09 +00004945 unsigned OrigMask = Mask;
4946 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004947 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004948 assert(Mask && TZ <= 3 && "illegal IT mask value!");
4949 for (unsigned i = 3; i != TZ; --i)
4950 Mask ^= 1 << i;
4951 } else
4952 Mask |= 0x10;
4953 MO.setImm(Mask);
Jim Grosbached16ec42011-08-29 22:24:09 +00004954
4955 // Set up the IT block state according to the IT instruction we just
4956 // matched.
4957 assert(!inITBlock() && "nested IT blocks?!");
4958 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
4959 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
4960 ITState.CurPosition = 0;
4961 ITState.FirstCond = true;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004962 break;
4963 }
Jim Grosbach8ba76c62011-08-11 17:35:48 +00004964 }
Jim Grosbachafad0532011-11-10 23:42:14 +00004965 return false;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00004966}
4967
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004968unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
4969 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
4970 // suffix depending on whether they're in an IT block or not.
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00004971 unsigned Opc = Inst.getOpcode();
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00004972 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004973 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
4974 assert(MCID.hasOptionalDef() &&
4975 "optionally flag setting instruction missing optional def operand");
4976 assert(MCID.NumOperands == Inst.getNumOperands() &&
4977 "operand count mismatch!");
4978 // Find the optional-def operand (cc_out).
4979 unsigned OpNo;
4980 for (OpNo = 0;
4981 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
4982 ++OpNo)
4983 ;
4984 // If we're parsing Thumb1, reject it completely.
4985 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
4986 return Match_MnemonicFail;
4987 // If we're parsing Thumb2, which form is legal depends on whether we're
4988 // in an IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00004989 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
4990 !inITBlock())
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004991 return Match_RequiresITBlock;
Jim Grosbached16ec42011-08-29 22:24:09 +00004992 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
4993 inITBlock())
4994 return Match_RequiresNotITBlock;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004995 }
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00004996 // Some high-register supporting Thumb1 encodings only allow both registers
4997 // to be from r0-r7 when in Thumb2.
4998 else if (Opc == ARM::tADDhirr && isThumbOne() &&
4999 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5000 isARMLowRegister(Inst.getOperand(2).getReg()))
5001 return Match_RequiresThumb2;
5002 // Others only require ARMv6 or later.
Jim Grosbachf86cd372011-08-19 20:46:54 +00005003 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00005004 isARMLowRegister(Inst.getOperand(0).getReg()) &&
5005 isARMLowRegister(Inst.getOperand(1).getReg()))
5006 return Match_RequiresV6;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00005007 return Match_Success;
5008}
5009
Chris Lattner9487de62010-10-28 21:28:01 +00005010bool ARMAsmParser::
5011MatchAndEmitInstruction(SMLoc IDLoc,
5012 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
5013 MCStreamer &Out) {
5014 MCInst Inst;
5015 unsigned ErrorInfo;
Jim Grosbach120a96a2011-08-15 23:03:29 +00005016 unsigned MatchResult;
Kevin Enderby3164a342010-12-09 19:19:43 +00005017 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby3164a342010-12-09 19:19:43 +00005018 switch (MatchResult) {
Jim Grosbach120a96a2011-08-15 23:03:29 +00005019 default: break;
Chris Lattnerd27b05e2010-10-28 21:41:58 +00005020 case Match_Success:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005021 // Context sensitive operand constraints aren't handled by the matcher,
5022 // so check them here.
Jim Grosbacha0d34d32011-09-02 23:22:08 +00005023 if (validateInstruction(Inst, Operands)) {
5024 // Still progress the IT block, otherwise one wrong condition causes
5025 // nasty cascading errors.
5026 forwardITPosition();
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005027 return true;
Jim Grosbacha0d34d32011-09-02 23:22:08 +00005028 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005029
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005030 // Some instructions need post-processing to, for example, tweak which
Jim Grosbachafad0532011-11-10 23:42:14 +00005031 // encoding is selected. Loop on it while changes happen so the
5032 // individual transformations can chain off each other. E.g.,
5033 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
5034 while (processInstruction(Inst, Operands))
5035 ;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005036
Jim Grosbacha0d34d32011-09-02 23:22:08 +00005037 // Only move forward at the very end so that everything in validate
5038 // and process gets a consistent answer about whether we're in an IT
5039 // block.
5040 forwardITPosition();
5041
Chris Lattner9487de62010-10-28 21:28:01 +00005042 Out.EmitInstruction(Inst);
5043 return false;
Chris Lattnerd27b05e2010-10-28 21:41:58 +00005044 case Match_MissingFeature:
5045 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
5046 return true;
5047 case Match_InvalidOperand: {
5048 SMLoc ErrorLoc = IDLoc;
5049 if (ErrorInfo != ~0U) {
5050 if (ErrorInfo >= Operands.size())
5051 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach624bcc72010-10-29 14:46:02 +00005052
Chris Lattnerd27b05e2010-10-28 21:41:58 +00005053 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
5054 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
5055 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00005056
Chris Lattnerd27b05e2010-10-28 21:41:58 +00005057 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattner9487de62010-10-28 21:28:01 +00005058 }
Chris Lattnerd27b05e2010-10-28 21:41:58 +00005059 case Match_MnemonicFail:
Jim Grosbach3e941ae2011-08-16 20:45:50 +00005060 return Error(IDLoc, "invalid instruction");
Daniel Dunbar66193402011-02-04 17:12:23 +00005061 case Match_ConversionFail:
Jim Grosbach8e048492011-08-19 22:07:46 +00005062 // The converter function will have already emited a diagnostic.
5063 return true;
Jim Grosbached16ec42011-08-29 22:24:09 +00005064 case Match_RequiresNotITBlock:
5065 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach3e941ae2011-08-16 20:45:50 +00005066 case Match_RequiresITBlock:
5067 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00005068 case Match_RequiresV6:
5069 return Error(IDLoc, "instruction variant requires ARMv6 or later");
5070 case Match_RequiresThumb2:
5071 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnerd27b05e2010-10-28 21:41:58 +00005072 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00005073
Eric Christopher91d7b902010-10-29 09:26:59 +00005074 llvm_unreachable("Implement any new match types added!");
Bill Wendlingee7f1f92010-11-06 21:42:12 +00005075 return true;
Chris Lattner9487de62010-10-28 21:28:01 +00005076}
5077
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005078/// parseDirective parses the arm specific directives
Kevin Enderbyccab3172009-09-15 00:27:25 +00005079bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
5080 StringRef IDVal = DirectiveID.getIdentifier();
5081 if (IDVal == ".word")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005082 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00005083 else if (IDVal == ".thumb")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005084 return parseDirectiveThumb(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00005085 else if (IDVal == ".thumb_func")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005086 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00005087 else if (IDVal == ".code")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005088 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00005089 else if (IDVal == ".syntax")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005090 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyccab3172009-09-15 00:27:25 +00005091 return true;
5092}
5093
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005094/// parseDirectiveWord
Kevin Enderbyccab3172009-09-15 00:27:25 +00005095/// ::= .word [ expression (, expression)* ]
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005096bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyccab3172009-09-15 00:27:25 +00005097 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5098 for (;;) {
5099 const MCExpr *Value;
5100 if (getParser().ParseExpression(Value))
5101 return true;
5102
Chris Lattnerc35681b2010-01-19 19:46:13 +00005103 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyccab3172009-09-15 00:27:25 +00005104
5105 if (getLexer().is(AsmToken::EndOfStatement))
5106 break;
Jim Grosbach624bcc72010-10-29 14:46:02 +00005107
Kevin Enderbyccab3172009-09-15 00:27:25 +00005108 // FIXME: Improve diagnostic.
5109 if (getLexer().isNot(AsmToken::Comma))
5110 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00005111 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00005112 }
5113 }
5114
Sean Callanana83fd7d2010-01-19 20:27:46 +00005115 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00005116 return false;
5117}
5118
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005119/// parseDirectiveThumb
Kevin Enderby146dcf22009-10-15 20:48:48 +00005120/// ::= .thumb
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005121bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby146dcf22009-10-15 20:48:48 +00005122 if (getLexer().isNot(AsmToken::EndOfStatement))
5123 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00005124 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00005125
5126 // TODO: set thumb mode
5127 // TODO: tell the MC streamer the mode
5128 // getParser().getStreamer().Emit???();
5129 return false;
5130}
5131
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005132/// parseDirectiveThumbFunc
Kevin Enderby146dcf22009-10-15 20:48:48 +00005133/// ::= .thumbfunc symbol_name
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005134bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00005135 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
5136 bool isMachO = MAI.hasSubsectionsViaSymbols();
5137 StringRef Name;
5138
5139 // Darwin asm has function name after .thumb_func direction
5140 // ELF doesn't
5141 if (isMachO) {
5142 const AsmToken &Tok = Parser.getTok();
5143 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
5144 return Error(L, "unexpected token in .thumb_func directive");
Jim Grosbach42ba6282011-11-10 20:48:53 +00005145 Name = Tok.getIdentifier();
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00005146 Parser.Lex(); // Consume the identifier token.
5147 }
5148
Jim Grosbach42ba6282011-11-10 20:48:53 +00005149 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby146dcf22009-10-15 20:48:48 +00005150 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00005151 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00005152
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00005153 // FIXME: assuming function name will be the line following .thumb_func
5154 if (!isMachO) {
Jim Grosbach42ba6282011-11-10 20:48:53 +00005155 Name = Parser.getTok().getIdentifier();
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00005156 }
5157
Jim Grosbachc6db8ce2010-11-05 22:33:53 +00005158 // Mark symbol as a thumb symbol.
5159 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
5160 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby146dcf22009-10-15 20:48:48 +00005161 return false;
5162}
5163
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005164/// parseDirectiveSyntax
Kevin Enderby146dcf22009-10-15 20:48:48 +00005165/// ::= .syntax unified | divided
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005166bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00005167 const AsmToken &Tok = Parser.getTok();
Kevin Enderby146dcf22009-10-15 20:48:48 +00005168 if (Tok.isNot(AsmToken::Identifier))
5169 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer92d89982010-07-14 22:38:02 +00005170 StringRef Mode = Tok.getString();
Duncan Sands257eba42010-06-29 13:04:35 +00005171 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callanana83fd7d2010-01-19 20:27:46 +00005172 Parser.Lex();
Duncan Sands257eba42010-06-29 13:04:35 +00005173 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderbye9f2f0c2011-01-27 23:22:36 +00005174 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby146dcf22009-10-15 20:48:48 +00005175 else
5176 return Error(L, "unrecognized syntax mode in .syntax directive");
5177
5178 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan936b0d32010-01-19 21:44:56 +00005179 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00005180 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00005181
5182 // TODO tell the MC streamer the mode
5183 // getParser().getStreamer().Emit???();
5184 return false;
5185}
5186
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005187/// parseDirectiveCode
Kevin Enderby146dcf22009-10-15 20:48:48 +00005188/// ::= .code 16 | 32
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005189bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00005190 const AsmToken &Tok = Parser.getTok();
Kevin Enderby146dcf22009-10-15 20:48:48 +00005191 if (Tok.isNot(AsmToken::Integer))
5192 return Error(L, "unexpected token in .code directive");
Sean Callanan936b0d32010-01-19 21:44:56 +00005193 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands257eba42010-06-29 13:04:35 +00005194 if (Val == 16)
Sean Callanana83fd7d2010-01-19 20:27:46 +00005195 Parser.Lex();
Duncan Sands257eba42010-06-29 13:04:35 +00005196 else if (Val == 32)
Sean Callanana83fd7d2010-01-19 20:27:46 +00005197 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00005198 else
5199 return Error(L, "invalid operand to .code directive");
5200
5201 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan936b0d32010-01-19 21:44:56 +00005202 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00005203 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00005204
Evan Cheng284b4672011-07-08 22:36:29 +00005205 if (Val == 16) {
Jim Grosbachf471ac32011-09-06 18:46:23 +00005206 if (!isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00005207 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00005208 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng284b4672011-07-08 22:36:29 +00005209 } else {
Jim Grosbachf471ac32011-09-06 18:46:23 +00005210 if (isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00005211 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00005212 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Cheng45543ba2011-07-08 22:49:55 +00005213 }
Jim Grosbach2db0ea02010-11-05 22:40:53 +00005214
Kevin Enderby146dcf22009-10-15 20:48:48 +00005215 return false;
5216}
5217
Sean Callanan643a5572010-04-07 20:29:34 +00005218extern "C" void LLVMInitializeARMAsmLexer();
5219
Kevin Enderby8be42bd2009-10-30 22:55:57 +00005220/// Force static initialization.
Kevin Enderbyccab3172009-09-15 00:27:25 +00005221extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng11424442011-07-26 00:24:13 +00005222 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
5223 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan643a5572010-04-07 20:29:34 +00005224 LLVMInitializeARMAsmLexer();
Kevin Enderbyccab3172009-09-15 00:27:25 +00005225}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00005226
Chris Lattner3e4582a2010-09-06 19:11:01 +00005227#define GET_REGISTER_MATCHER
5228#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00005229#include "ARMGenAsmMatcher.inc"