blob: c24335ca353c26a8bd24a10acdfdf80e492d9413 [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
Jim Grosbachcd6f5e72011-11-30 01:09:44 +000042enum VectorLaneTy { NoLanes, AllLanes };
43
Evan Cheng11424442011-07-26 00:24:13 +000044class ARMAsmParser : public MCTargetAsmParser {
Evan Cheng91111d22011-07-09 05:47:46 +000045 MCSubtargetInfo &STI;
Kevin Enderbyccab3172009-09-15 00:27:25 +000046 MCAsmParser &Parser;
47
Jim Grosbached16ec42011-08-29 22:24:09 +000048 struct {
49 ARMCC::CondCodes Cond; // Condition for IT block.
50 unsigned Mask:4; // Condition mask for instructions.
51 // Starting at first 1 (from lsb).
52 // '1' condition as indicated in IT.
53 // '0' inverse of condition (else).
54 // Count of instructions in IT block is
55 // 4 - trailingzeroes(mask)
56
57 bool FirstCond; // Explicit flag for when we're parsing the
58 // First instruction in the IT block. It's
59 // implied in the mask, so needs special
60 // handling.
61
62 unsigned CurPosition; // Current position in parsing of IT
63 // block. In range [0,3]. Initialized
64 // according to count of instructions in block.
65 // ~0U if no active IT block.
66 } ITState;
67 bool inITBlock() { return ITState.CurPosition != ~0U;}
Jim Grosbacha0d34d32011-09-02 23:22:08 +000068 void forwardITPosition() {
69 if (!inITBlock()) return;
70 // Move to the next instruction in the IT block, if there is one. If not,
71 // mark the block as done.
72 unsigned TZ = CountTrailingZeros_32(ITState.Mask);
73 if (++ITState.CurPosition == 5 - TZ)
74 ITState.CurPosition = ~0U; // Done with the IT block after this.
75 }
Jim Grosbached16ec42011-08-29 22:24:09 +000076
77
Kevin Enderbyccab3172009-09-15 00:27:25 +000078 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyccab3172009-09-15 00:27:25 +000079 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
80
81 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
Kevin Enderbyccab3172009-09-15 00:27:25 +000082 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
83
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000084 int tryParseRegister();
85 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d6022d2011-07-26 20:41:24 +000086 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000087 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd3595712011-08-03 23:50:40 +000088 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000089 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
90 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbachd3595712011-08-03 23:50:40 +000091 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
92 unsigned &ShiftAmount);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000093 bool parseDirectiveWord(unsigned Size, SMLoc L);
94 bool parseDirectiveThumb(SMLoc L);
95 bool parseDirectiveThumbFunc(SMLoc L);
96 bool parseDirectiveCode(SMLoc L);
97 bool parseDirectiveSyntax(SMLoc L);
Kevin Enderby146dcf22009-10-15 20:48:48 +000098
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000099 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000100 bool &CarrySetting, unsigned &ProcessorIMod,
101 StringRef &ITMask);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000102 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +0000103 bool &CanAcceptPredicationCode);
Jim Grosbach624bcc72010-10-29 14:46:02 +0000104
Evan Cheng4d1ca962011-07-08 01:53:10 +0000105 bool isThumb() const {
106 // FIXME: Can tablegen auto-generate this?
Evan Cheng91111d22011-07-09 05:47:46 +0000107 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000108 }
Evan Cheng4d1ca962011-07-08 01:53:10 +0000109 bool isThumbOne() const {
Evan Cheng91111d22011-07-09 05:47:46 +0000110 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000111 }
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000112 bool isThumbTwo() const {
113 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
114 }
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000115 bool hasV6Ops() const {
116 return STI.getFeatureBits() & ARM::HasV6Ops;
117 }
James Molloy21efa7d2011-09-28 14:21:38 +0000118 bool hasV7Ops() const {
119 return STI.getFeatureBits() & ARM::HasV7Ops;
120 }
Evan Cheng284b4672011-07-08 22:36:29 +0000121 void SwitchMode() {
Evan Cheng91111d22011-07-09 05:47:46 +0000122 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
123 setAvailableFeatures(FB);
Evan Cheng284b4672011-07-08 22:36:29 +0000124 }
James Molloy21efa7d2011-09-28 14:21:38 +0000125 bool isMClass() const {
126 return STI.getFeatureBits() & ARM::FeatureMClass;
127 }
Evan Cheng4d1ca962011-07-08 01:53:10 +0000128
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000129 /// @name Auto-generated Match Functions
130 /// {
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +0000131
Chris Lattner3e4582a2010-09-06 19:11:01 +0000132#define GET_ASSEMBLER_HEADER
133#include "ARMGenAsmMatcher.inc"
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000134
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000135 /// }
136
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000137 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000138 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbach861e49c2011-02-12 01:34:40 +0000139 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000140 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbach861e49c2011-02-12 01:34:40 +0000141 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach48399582011-10-12 17:34:41 +0000142 OperandMatchResultTy parseCoprocOptionOperand(
143 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000144 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopescdd20af2011-02-18 19:49:06 +0000145 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000146 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopescdd20af2011-02-18 19:49:06 +0000147 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000148 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopescdd20af2011-02-18 19:49:06 +0000149 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach27c1e252011-07-21 17:23:04 +0000150 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
151 StringRef Op, int Low, int High);
152 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
153 return parsePKHImm(O, "lsl", 0, 31);
154 }
155 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
156 return parsePKHImm(O, "asr", 1, 32);
157 }
Jim Grosbach0a547702011-07-22 17:44:50 +0000158 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000159 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach833b9d32011-07-27 20:15:40 +0000160 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach864b6092011-07-28 21:34:26 +0000161 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachd3595712011-08-03 23:50:40 +0000162 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach1d9d5e92011-08-10 21:56:18 +0000163 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbache7fbce72011-10-03 23:38:36 +0000164 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000165 OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachcd6f5e72011-11-30 01:09:44 +0000166 OperandMatchResultTy parseVectorLane(VectorLaneTy &LaneKind);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000167
168 // Asm Match Converter Methods
Jim Grosbach7db8d692011-09-08 22:07:06 +0000169 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
170 const SmallVectorImpl<MCParsedAsmOperand*> &);
171 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
172 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachc086f682011-09-08 00:39:19 +0000173 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
174 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach9c0b86a2011-09-16 21:55:56 +0000175 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
176 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000177 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000178 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson16d33f32011-08-26 20:43:14 +0000179 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
180 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd564bf32011-08-11 19:22:40 +0000181 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
182 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000183 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000184 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd886f8c2011-08-11 21:17:22 +0000185 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
186 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd3595712011-08-03 23:50:40 +0000187 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
188 const SmallVectorImpl<MCParsedAsmOperand*> &);
189 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
190 const SmallVectorImpl<MCParsedAsmOperand*> &);
191 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
192 const SmallVectorImpl<MCParsedAsmOperand*> &);
193 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
194 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach5b96b802011-08-10 20:29:19 +0000195 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
196 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheb09f492011-08-11 20:28:23 +0000197 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
198 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachcd4dd252011-08-10 22:42:16 +0000199 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
200 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach8e048492011-08-19 22:07:46 +0000201 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
202 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach3ea06572011-10-24 22:16:58 +0000203 bool cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
204 const SmallVectorImpl<MCParsedAsmOperand*> &);
205 bool cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
206 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach05df4602011-10-31 21:50:31 +0000207 bool cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
208 const SmallVectorImpl<MCParsedAsmOperand*> &);
209 bool cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
210 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000211
212 bool validateInstruction(MCInst &Inst,
213 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachafad0532011-11-10 23:42:14 +0000214 bool processInstruction(MCInst &Inst,
Jim Grosbach8ba76c62011-08-11 17:35:48 +0000215 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach7283da92011-08-16 21:12:37 +0000216 bool shouldOmitCCOutOperand(StringRef Mnemonic,
217 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000218
Kevin Enderbyccab3172009-09-15 00:27:25 +0000219public:
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000220 enum ARMMatchResultTy {
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000221 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbached16ec42011-08-29 22:24:09 +0000222 Match_RequiresNotITBlock,
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000223 Match_RequiresV6,
224 Match_RequiresThumb2
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000225 };
226
Evan Cheng91111d22011-07-09 05:47:46 +0000227 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng11424442011-07-26 00:24:13 +0000228 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Cheng4d1ca962011-07-08 01:53:10 +0000229 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng284b4672011-07-08 22:36:29 +0000230
Evan Cheng4d1ca962011-07-08 01:53:10 +0000231 // Initialize the set of available features.
Evan Cheng91111d22011-07-09 05:47:46 +0000232 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbached16ec42011-08-29 22:24:09 +0000233
234 // Not in an ITBlock to start with.
235 ITState.CurPosition = ~0U;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000236 }
Kevin Enderbyccab3172009-09-15 00:27:25 +0000237
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000238 // Implementation of the MCTargetAsmParser interface:
239 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
240 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000241 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000242 bool ParseDirective(AsmToken DirectiveID);
243
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000244 unsigned checkTargetMatchPredicate(MCInst &Inst);
245
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000246 bool MatchAndEmitInstruction(SMLoc IDLoc,
247 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
248 MCStreamer &Out);
Kevin Enderbyccab3172009-09-15 00:27:25 +0000249};
Jim Grosbach624bcc72010-10-29 14:46:02 +0000250} // end anonymous namespace
251
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +0000252namespace {
253
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000254/// ARMOperand - Instances of this class represent a parsed ARM machine
255/// instruction.
Bill Wendlingee7f1f92010-11-06 21:42:12 +0000256class ARMOperand : public MCParsedAsmOperand {
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000257 enum KindTy {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000258 k_CondCode,
259 k_CCOut,
260 k_ITCondMask,
261 k_CoprocNum,
262 k_CoprocReg,
Jim Grosbach48399582011-10-12 17:34:41 +0000263 k_CoprocOption,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000264 k_Immediate,
265 k_FPImmediate,
266 k_MemBarrierOpt,
267 k_Memory,
268 k_PostIndexRegister,
269 k_MSRMask,
270 k_ProcIFlags,
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000271 k_VectorIndex,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000272 k_Register,
273 k_RegisterList,
274 k_DPRRegisterList,
275 k_SPRRegisterList,
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000276 k_VectorList,
Jim Grosbachcd6f5e72011-11-30 01:09:44 +0000277 k_VectorListAllLanes,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000278 k_ShiftedRegister,
279 k_ShiftedImmediate,
280 k_ShifterImmediate,
281 k_RotateImmediate,
282 k_BitfieldDescriptor,
283 k_Token
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000284 } Kind;
285
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000286 SMLoc StartLoc, EndLoc;
Bill Wendling0ab0f672010-11-18 21:50:54 +0000287 SmallVector<unsigned, 8> Registers;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000288
289 union {
290 struct {
Daniel Dunbard8042b72010-08-11 06:36:53 +0000291 ARMCC::CondCodes Val;
292 } CC;
293
294 struct {
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000295 unsigned Val;
296 } Cop;
297
298 struct {
Jim Grosbach48399582011-10-12 17:34:41 +0000299 unsigned Val;
300 } CoprocOption;
301
302 struct {
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000303 unsigned Mask:4;
304 } ITMask;
305
306 struct {
307 ARM_MB::MemBOpt Val;
308 } MBOpt;
309
310 struct {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000311 ARM_PROC::IFlags Val;
312 } IFlags;
313
314 struct {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000315 unsigned Val;
316 } MMask;
317
318 struct {
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000319 const char *Data;
320 unsigned Length;
321 } Tok;
322
323 struct {
324 unsigned RegNum;
325 } Reg;
326
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000327 // A vector register list is a sequential list of 1 to 4 registers.
328 struct {
329 unsigned RegNum;
330 unsigned Count;
331 } VectorList;
332
Bill Wendlingb884a8e2010-11-06 22:19:43 +0000333 struct {
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000334 unsigned Val;
335 } VectorIndex;
336
337 struct {
Kevin Enderbyf5079942009-10-13 22:19:02 +0000338 const MCExpr *Val;
339 } Imm;
Jim Grosbach624bcc72010-10-29 14:46:02 +0000340
Jim Grosbache7fbce72011-10-03 23:38:36 +0000341 struct {
342 unsigned Val; // encoded 8-bit representation
343 } FPImm;
344
Daniel Dunbar2be732a2011-01-10 15:26:21 +0000345 /// Combined record for all forms of ARM address expressions.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000346 struct {
347 unsigned BaseRegNum;
Jim Grosbachd3595712011-08-03 23:50:40 +0000348 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
349 // was specified.
350 const MCConstantExpr *OffsetImm; // Offset immediate value
351 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
352 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbacha95ec992011-10-11 17:29:55 +0000353 unsigned ShiftImm; // shift for OffsetReg.
354 unsigned Alignment; // 0 = no alignment specified
355 // n = alignment in bytes (8, 16, or 32)
Jim Grosbachd3595712011-08-03 23:50:40 +0000356 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbach871dff72011-10-11 15:59:20 +0000357 } Memory;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000358
359 struct {
Jim Grosbachd3595712011-08-03 23:50:40 +0000360 unsigned RegNum;
Jim Grosbachc320c852011-08-05 21:28:30 +0000361 bool isAdd;
362 ARM_AM::ShiftOpc ShiftTy;
363 unsigned ShiftImm;
Jim Grosbachd3595712011-08-03 23:50:40 +0000364 } PostIdxReg;
365
366 struct {
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000367 bool isASR;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000368 unsigned Imm;
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000369 } ShifterImm;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000370 struct {
371 ARM_AM::ShiftOpc ShiftTy;
372 unsigned SrcReg;
373 unsigned ShiftReg;
374 unsigned ShiftImm;
Jim Grosbachac798e12011-07-25 20:49:51 +0000375 } RegShiftedReg;
Owen Andersonb595ed02011-07-21 18:54:16 +0000376 struct {
377 ARM_AM::ShiftOpc ShiftTy;
378 unsigned SrcReg;
379 unsigned ShiftImm;
Jim Grosbachac798e12011-07-25 20:49:51 +0000380 } RegShiftedImm;
Jim Grosbach833b9d32011-07-27 20:15:40 +0000381 struct {
382 unsigned Imm;
383 } RotImm;
Jim Grosbach864b6092011-07-28 21:34:26 +0000384 struct {
385 unsigned LSB;
386 unsigned Width;
387 } Bitfield;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000388 };
Jim Grosbach624bcc72010-10-29 14:46:02 +0000389
Bill Wendlingee7f1f92010-11-06 21:42:12 +0000390 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
391public:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000392 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
393 Kind = o.Kind;
394 StartLoc = o.StartLoc;
395 EndLoc = o.EndLoc;
396 switch (Kind) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000397 case k_CondCode:
Daniel Dunbard8042b72010-08-11 06:36:53 +0000398 CC = o.CC;
399 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000400 case k_ITCondMask:
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000401 ITMask = o.ITMask;
402 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000403 case k_Token:
Daniel Dunbard8042b72010-08-11 06:36:53 +0000404 Tok = o.Tok;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000405 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000406 case k_CCOut:
407 case k_Register:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000408 Reg = o.Reg;
409 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000410 case k_RegisterList:
411 case k_DPRRegisterList:
412 case k_SPRRegisterList:
Bill Wendling0ab0f672010-11-18 21:50:54 +0000413 Registers = o.Registers;
Bill Wendling7cef4472010-11-06 19:56:04 +0000414 break;
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000415 case k_VectorList:
Jim Grosbachcd6f5e72011-11-30 01:09:44 +0000416 case k_VectorListAllLanes:
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000417 VectorList = o.VectorList;
418 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000419 case k_CoprocNum:
420 case k_CoprocReg:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000421 Cop = o.Cop;
422 break;
Jim Grosbach48399582011-10-12 17:34:41 +0000423 case k_CoprocOption:
424 CoprocOption = o.CoprocOption;
425 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000426 case k_Immediate:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000427 Imm = o.Imm;
428 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000429 case k_FPImmediate:
Jim Grosbache7fbce72011-10-03 23:38:36 +0000430 FPImm = o.FPImm;
431 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000432 case k_MemBarrierOpt:
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000433 MBOpt = o.MBOpt;
434 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000435 case k_Memory:
Jim Grosbach871dff72011-10-11 15:59:20 +0000436 Memory = o.Memory;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000437 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000438 case k_PostIndexRegister:
Jim Grosbachd3595712011-08-03 23:50:40 +0000439 PostIdxReg = o.PostIdxReg;
440 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000441 case k_MSRMask:
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000442 MMask = o.MMask;
443 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000444 case k_ProcIFlags:
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000445 IFlags = o.IFlags;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000446 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000447 case k_ShifterImmediate:
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000448 ShifterImm = o.ShifterImm;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000449 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000450 case k_ShiftedRegister:
Jim Grosbachac798e12011-07-25 20:49:51 +0000451 RegShiftedReg = o.RegShiftedReg;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000452 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000453 case k_ShiftedImmediate:
Jim Grosbachac798e12011-07-25 20:49:51 +0000454 RegShiftedImm = o.RegShiftedImm;
Owen Andersonb595ed02011-07-21 18:54:16 +0000455 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000456 case k_RotateImmediate:
Jim Grosbach833b9d32011-07-27 20:15:40 +0000457 RotImm = o.RotImm;
458 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000459 case k_BitfieldDescriptor:
Jim Grosbach864b6092011-07-28 21:34:26 +0000460 Bitfield = o.Bitfield;
461 break;
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000462 case k_VectorIndex:
463 VectorIndex = o.VectorIndex;
464 break;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000465 }
466 }
Jim Grosbach624bcc72010-10-29 14:46:02 +0000467
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000468 /// getStartLoc - Get the location of the first token of this operand.
469 SMLoc getStartLoc() const { return StartLoc; }
470 /// getEndLoc - Get the location of the last token of this operand.
471 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000472
Daniel Dunbard8042b72010-08-11 06:36:53 +0000473 ARMCC::CondCodes getCondCode() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000474 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbard8042b72010-08-11 06:36:53 +0000475 return CC.Val;
476 }
477
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000478 unsigned getCoproc() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000479 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000480 return Cop.Val;
481 }
482
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000483 StringRef getToken() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000484 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000485 return StringRef(Tok.Data, Tok.Length);
486 }
487
488 unsigned getReg() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000489 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling2cae3272010-11-09 22:44:22 +0000490 return Reg.RegNum;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000491 }
492
Bill Wendlingbed94652010-11-09 23:28:44 +0000493 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000494 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
495 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling0ab0f672010-11-18 21:50:54 +0000496 return Registers;
Bill Wendling7cef4472010-11-06 19:56:04 +0000497 }
498
Kevin Enderbyf5079942009-10-13 22:19:02 +0000499 const MCExpr *getImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000500 assert(Kind == k_Immediate && "Invalid access!");
Kevin Enderbyf5079942009-10-13 22:19:02 +0000501 return Imm.Val;
502 }
503
Jim Grosbache7fbce72011-10-03 23:38:36 +0000504 unsigned getFPImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000505 assert(Kind == k_FPImmediate && "Invalid access!");
Jim Grosbache7fbce72011-10-03 23:38:36 +0000506 return FPImm.Val;
507 }
508
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000509 unsigned getVectorIndex() const {
510 assert(Kind == k_VectorIndex && "Invalid access!");
511 return VectorIndex.Val;
512 }
513
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000514 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000515 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000516 return MBOpt.Val;
517 }
518
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000519 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000520 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000521 return IFlags.Val;
522 }
523
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000524 unsigned getMSRMask() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000525 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000526 return MMask.Val;
527 }
528
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000529 bool isCoprocNum() const { return Kind == k_CoprocNum; }
530 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach48399582011-10-12 17:34:41 +0000531 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000532 bool isCondCode() const { return Kind == k_CondCode; }
533 bool isCCOut() const { return Kind == k_CCOut; }
534 bool isITMask() const { return Kind == k_ITCondMask; }
535 bool isITCondCode() const { return Kind == k_CondCode; }
536 bool isImm() const { return Kind == k_Immediate; }
537 bool isFPImm() const { return Kind == k_FPImmediate; }
Jim Grosbach7db8d692011-09-08 22:07:06 +0000538 bool isImm8s4() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000539 if (Kind != k_Immediate)
Jim Grosbach7db8d692011-09-08 22:07:06 +0000540 return false;
541 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
542 if (!CE) return false;
543 int64_t Value = CE->getValue();
544 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
545 }
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000546 bool isImm0_1020s4() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000547 if (Kind != k_Immediate)
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000548 return false;
549 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
550 if (!CE) return false;
551 int64_t Value = CE->getValue();
552 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
553 }
554 bool isImm0_508s4() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000555 if (Kind != k_Immediate)
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000556 return false;
557 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
558 if (!CE) return false;
559 int64_t Value = CE->getValue();
560 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
561 }
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000562 bool isImm0_255() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000563 if (Kind != k_Immediate)
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000564 return false;
565 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
566 if (!CE) return false;
567 int64_t Value = CE->getValue();
568 return Value >= 0 && Value < 256;
569 }
Jim Grosbach31756c22011-07-13 22:01:08 +0000570 bool isImm0_7() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000571 if (Kind != k_Immediate)
Jim Grosbach31756c22011-07-13 22:01:08 +0000572 return false;
573 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
574 if (!CE) return false;
575 int64_t Value = CE->getValue();
576 return Value >= 0 && Value < 8;
577 }
578 bool isImm0_15() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000579 if (Kind != k_Immediate)
Jim Grosbach31756c22011-07-13 22:01:08 +0000580 return false;
581 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
582 if (!CE) return false;
583 int64_t Value = CE->getValue();
584 return Value >= 0 && Value < 16;
585 }
Jim Grosbach72e7c4f2011-07-21 23:26:25 +0000586 bool isImm0_31() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000587 if (Kind != k_Immediate)
Jim Grosbach72e7c4f2011-07-21 23:26:25 +0000588 return false;
589 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
590 if (!CE) return false;
591 int64_t Value = CE->getValue();
592 return Value >= 0 && Value < 32;
593 }
Jim Grosbach475c6db2011-07-25 23:09:14 +0000594 bool isImm1_16() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000595 if (Kind != k_Immediate)
Jim Grosbach475c6db2011-07-25 23:09:14 +0000596 return false;
597 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
598 if (!CE) return false;
599 int64_t Value = CE->getValue();
600 return Value > 0 && Value < 17;
601 }
Jim Grosbach801e0a32011-07-22 23:16:18 +0000602 bool isImm1_32() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000603 if (Kind != k_Immediate)
Jim Grosbach801e0a32011-07-22 23:16:18 +0000604 return false;
605 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
606 if (!CE) return false;
607 int64_t Value = CE->getValue();
608 return Value > 0 && Value < 33;
609 }
Jim Grosbachc14871c2011-11-10 19:18:01 +0000610 bool isImm0_32() const {
611 if (Kind != k_Immediate)
612 return false;
613 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
614 if (!CE) return false;
615 int64_t Value = CE->getValue();
616 return Value >= 0 && Value < 33;
617 }
Jim Grosbach975b6412011-07-13 20:10:10 +0000618 bool isImm0_65535() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000619 if (Kind != k_Immediate)
Jim Grosbach975b6412011-07-13 20:10:10 +0000620 return false;
621 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
622 if (!CE) return false;
623 int64_t Value = CE->getValue();
624 return Value >= 0 && Value < 65536;
625 }
Jim Grosbach7c09e3c2011-07-19 19:13:28 +0000626 bool isImm0_65535Expr() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000627 if (Kind != k_Immediate)
Jim Grosbach7c09e3c2011-07-19 19:13:28 +0000628 return false;
629 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
630 // If it's not a constant expression, it'll generate a fixup and be
631 // handled later.
632 if (!CE) return true;
633 int64_t Value = CE->getValue();
634 return Value >= 0 && Value < 65536;
635 }
Jim Grosbachf1637842011-07-26 16:24:27 +0000636 bool isImm24bit() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000637 if (Kind != k_Immediate)
Jim Grosbachf1637842011-07-26 16:24:27 +0000638 return false;
639 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
640 if (!CE) return false;
641 int64_t Value = CE->getValue();
642 return Value >= 0 && Value <= 0xffffff;
643 }
Jim Grosbach46dd4132011-08-17 21:51:27 +0000644 bool isImmThumbSR() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000645 if (Kind != k_Immediate)
Jim Grosbach46dd4132011-08-17 21:51:27 +0000646 return false;
647 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
648 if (!CE) return false;
649 int64_t Value = CE->getValue();
650 return Value > 0 && Value < 33;
651 }
Jim Grosbach27c1e252011-07-21 17:23:04 +0000652 bool isPKHLSLImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000653 if (Kind != k_Immediate)
Jim Grosbach27c1e252011-07-21 17:23:04 +0000654 return false;
655 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
656 if (!CE) return false;
657 int64_t Value = CE->getValue();
658 return Value >= 0 && Value < 32;
659 }
660 bool isPKHASRImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000661 if (Kind != k_Immediate)
Jim Grosbach27c1e252011-07-21 17:23:04 +0000662 return false;
663 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
664 if (!CE) return false;
665 int64_t Value = CE->getValue();
666 return Value > 0 && Value <= 32;
667 }
Jim Grosbach9720dcf2011-07-19 16:50:30 +0000668 bool isARMSOImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000669 if (Kind != k_Immediate)
Jim Grosbach9720dcf2011-07-19 16:50:30 +0000670 return false;
671 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
672 if (!CE) return false;
673 int64_t Value = CE->getValue();
674 return ARM_AM::getSOImmVal(Value) != -1;
675 }
Jim Grosbach3d785ed2011-10-28 22:50:54 +0000676 bool isARMSOImmNot() const {
677 if (Kind != k_Immediate)
678 return false;
679 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
680 if (!CE) return false;
681 int64_t Value = CE->getValue();
682 return ARM_AM::getSOImmVal(~Value) != -1;
683 }
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000684 bool isT2SOImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000685 if (Kind != k_Immediate)
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000686 return false;
687 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
688 if (!CE) return false;
689 int64_t Value = CE->getValue();
690 return ARM_AM::getT2SOImmVal(Value) != -1;
691 }
Jim Grosbachb009a872011-10-28 22:36:30 +0000692 bool isT2SOImmNot() const {
693 if (Kind != k_Immediate)
694 return false;
695 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
696 if (!CE) return false;
697 int64_t Value = CE->getValue();
698 return ARM_AM::getT2SOImmVal(~Value) != -1;
699 }
Jim Grosbach0a547702011-07-22 17:44:50 +0000700 bool isSetEndImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000701 if (Kind != k_Immediate)
Jim Grosbach0a547702011-07-22 17:44:50 +0000702 return false;
703 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
704 if (!CE) return false;
705 int64_t Value = CE->getValue();
706 return Value == 1 || Value == 0;
707 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000708 bool isReg() const { return Kind == k_Register; }
709 bool isRegList() const { return Kind == k_RegisterList; }
710 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
711 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
712 bool isToken() const { return Kind == k_Token; }
713 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
714 bool isMemory() const { return Kind == k_Memory; }
715 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
716 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
717 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
718 bool isRotImm() const { return Kind == k_RotateImmediate; }
719 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
720 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachc320c852011-08-05 21:28:30 +0000721 bool isPostIdxReg() const {
Jim Grosbachee201fa2011-11-14 17:52:47 +0000722 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachc320c852011-08-05 21:28:30 +0000723 }
Jim Grosbacha95ec992011-10-11 17:29:55 +0000724 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachc11b7c32011-10-10 23:06:42 +0000725 if (!isMemory())
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000726 return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000727 // No offset of any kind.
Jim Grosbacha95ec992011-10-11 17:29:55 +0000728 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
729 (alignOK || Memory.Alignment == 0);
730 }
731 bool isAlignedMemory() const {
732 return isMemNoOffset(true);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000733 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000734 bool isAddrMode2() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000735 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000736 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000737 if (Memory.OffsetRegNum) return true;
Jim Grosbachd3595712011-08-03 23:50:40 +0000738 // Immediate offset in range [-4095, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +0000739 if (!Memory.OffsetImm) return true;
740 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachd3595712011-08-03 23:50:40 +0000741 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +0000742 }
Jim Grosbachcd17c122011-08-04 23:01:30 +0000743 bool isAM2OffsetImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000744 if (Kind != k_Immediate)
Jim Grosbachcd17c122011-08-04 23:01:30 +0000745 return false;
746 // Immediate offset in range [-4095, 4095].
747 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
748 if (!CE) return false;
749 int64_t Val = CE->getValue();
750 return Val > -4096 && Val < 4096;
751 }
Jim Grosbach5b96b802011-08-10 20:29:19 +0000752 bool isAddrMode3() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000753 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000754 // No shifts are legal for AM3.
Jim Grosbach871dff72011-10-11 15:59:20 +0000755 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000756 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000757 if (Memory.OffsetRegNum) return true;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000758 // Immediate offset in range [-255, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +0000759 if (!Memory.OffsetImm) return true;
760 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach5b96b802011-08-10 20:29:19 +0000761 return Val > -256 && Val < 256;
762 }
763 bool isAM3Offset() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000764 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach5b96b802011-08-10 20:29:19 +0000765 return false;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000766 if (Kind == k_PostIndexRegister)
Jim Grosbach5b96b802011-08-10 20:29:19 +0000767 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
768 // Immediate offset in range [-255, 255].
769 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
770 if (!CE) return false;
771 int64_t Val = CE->getValue();
Jim Grosbach1d9d5e92011-08-10 21:56:18 +0000772 // Special case, #-0 is INT32_MIN.
773 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000774 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000775 bool isAddrMode5() const {
Jim Grosbachfb2f1d62011-11-01 01:24:45 +0000776 // If we have an immediate that's not a constant, treat it as a label
777 // reference needing a fixup. If it is a constant, it's something else
778 // and we reject it.
779 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
780 return true;
Jim Grosbacha95ec992011-10-11 17:29:55 +0000781 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000782 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000783 if (Memory.OffsetRegNum) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000784 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbach871dff72011-10-11 15:59:20 +0000785 if (!Memory.OffsetImm) return true;
786 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson967674d2011-08-29 19:36:44 +0000787 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbachfb2f1d62011-11-01 01:24:45 +0000788 Val == INT32_MIN;
Bill Wendling8d2aa032010-11-08 23:49:57 +0000789 }
Jim Grosbach05541f42011-09-19 22:21:13 +0000790 bool isMemTBB() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000791 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000792 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach05541f42011-09-19 22:21:13 +0000793 return false;
794 return true;
795 }
796 bool isMemTBH() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000797 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000798 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
799 Memory.Alignment != 0 )
Jim Grosbach05541f42011-09-19 22:21:13 +0000800 return false;
801 return true;
802 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000803 bool isMemRegOffset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000804 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendling092a7bd2010-12-14 03:36:38 +0000805 return false;
Daniel Dunbar7ed45592011-01-18 05:34:11 +0000806 return true;
Bill Wendling092a7bd2010-12-14 03:36:38 +0000807 }
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000808 bool isT2MemRegOffset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000809 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
810 Memory.Alignment != 0)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000811 return false;
812 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbach871dff72011-10-11 15:59:20 +0000813 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000814 return true;
Jim Grosbach871dff72011-10-11 15:59:20 +0000815 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000816 return false;
817 return true;
818 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000819 bool isMemThumbRR() const {
820 // Thumb reg+reg addressing is simple. Just two registers, a base and
821 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbach871dff72011-10-11 15:59:20 +0000822 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000823 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendling811c9362010-11-30 07:44:32 +0000824 return false;
Jim Grosbach871dff72011-10-11 15:59:20 +0000825 return isARMLowRegister(Memory.BaseRegNum) &&
826 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach3fe94e32011-08-19 17:55:24 +0000827 }
828 bool isMemThumbRIs4() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000829 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000830 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach3fe94e32011-08-19 17:55:24 +0000831 return false;
832 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbach871dff72011-10-11 15:59:20 +0000833 if (!Memory.OffsetImm) return true;
834 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach23983d62011-08-19 18:13:48 +0000835 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
836 }
Jim Grosbach26d35872011-08-19 18:55:51 +0000837 bool isMemThumbRIs2() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000838 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000839 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach26d35872011-08-19 18:55:51 +0000840 return false;
841 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbach871dff72011-10-11 15:59:20 +0000842 if (!Memory.OffsetImm) return true;
843 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach26d35872011-08-19 18:55:51 +0000844 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
845 }
Jim Grosbacha32c7532011-08-19 18:49:59 +0000846 bool isMemThumbRIs1() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000847 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000848 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbacha32c7532011-08-19 18:49:59 +0000849 return false;
850 // Immediate offset in range [0, 31].
Jim Grosbach871dff72011-10-11 15:59:20 +0000851 if (!Memory.OffsetImm) return true;
852 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha32c7532011-08-19 18:49:59 +0000853 return Val >= 0 && Val <= 31;
854 }
Jim Grosbach23983d62011-08-19 18:13:48 +0000855 bool isMemThumbSPI() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000856 if (!isMemory() || Memory.OffsetRegNum != 0 ||
857 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbach23983d62011-08-19 18:13:48 +0000858 return false;
859 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +0000860 if (!Memory.OffsetImm) return true;
861 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach23983d62011-08-19 18:13:48 +0000862 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendling811c9362010-11-30 07:44:32 +0000863 }
Jim Grosbach7db8d692011-09-08 22:07:06 +0000864 bool isMemImm8s4Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000865 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7db8d692011-09-08 22:07:06 +0000866 return false;
867 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +0000868 if (!Memory.OffsetImm) return true;
869 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7db8d692011-09-08 22:07:06 +0000870 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
871 }
Jim Grosbacha05627e2011-09-09 18:37:27 +0000872 bool isMemImm0_1020s4Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000873 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha05627e2011-09-09 18:37:27 +0000874 return false;
875 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +0000876 if (!Memory.OffsetImm) return true;
877 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha05627e2011-09-09 18:37:27 +0000878 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
879 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000880 bool isMemImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000881 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachd3595712011-08-03 23:50:40 +0000882 return false;
883 // Immediate offset in range [-255, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +0000884 if (!Memory.OffsetImm) return true;
885 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson49168402011-09-23 22:25:02 +0000886 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbachd3595712011-08-03 23:50:40 +0000887 }
Jim Grosbach2392c532011-09-07 23:39:14 +0000888 bool isMemPosImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000889 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach2392c532011-09-07 23:39:14 +0000890 return false;
891 // Immediate offset in range [0, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +0000892 if (!Memory.OffsetImm) return true;
893 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2392c532011-09-07 23:39:14 +0000894 return Val >= 0 && Val < 256;
895 }
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +0000896 bool isMemNegImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000897 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +0000898 return false;
899 // Immediate offset in range [-255, -1].
Jim Grosbach871dff72011-10-11 15:59:20 +0000900 if (!Memory.OffsetImm) return true;
901 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +0000902 return Val > -256 && Val < 0;
903 }
904 bool isMemUImm12Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000905 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +0000906 return false;
907 // Immediate offset in range [0, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +0000908 if (!Memory.OffsetImm) return true;
909 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +0000910 return (Val >= 0 && Val < 4096);
911 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000912 bool isMemImm12Offset() const {
Jim Grosbach95466ce2011-08-08 20:59:31 +0000913 // If we have an immediate that's not a constant, treat it as a label
914 // reference needing a fixup. If it is a constant, it's something else
915 // and we reject it.
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000916 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach95466ce2011-08-08 20:59:31 +0000917 return true;
918
Jim Grosbacha95ec992011-10-11 17:29:55 +0000919 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachd3595712011-08-03 23:50:40 +0000920 return false;
921 // Immediate offset in range [-4095, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +0000922 if (!Memory.OffsetImm) return true;
923 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson967674d2011-08-29 19:36:44 +0000924 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbachd3595712011-08-03 23:50:40 +0000925 }
926 bool isPostIdxImm8() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000927 if (Kind != k_Immediate)
Jim Grosbachd3595712011-08-03 23:50:40 +0000928 return false;
929 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
930 if (!CE) return false;
931 int64_t Val = CE->getValue();
Owen Andersonf02d98d2011-08-29 17:17:09 +0000932 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbachd3595712011-08-03 23:50:40 +0000933 }
Jim Grosbach93981412011-10-11 21:55:36 +0000934 bool isPostIdxImm8s4() const {
935 if (Kind != k_Immediate)
936 return false;
937 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
938 if (!CE) return false;
939 int64_t Val = CE->getValue();
940 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
941 (Val == INT32_MIN);
942 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000943
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000944 bool isMSRMask() const { return Kind == k_MSRMask; }
945 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +0000946
Jim Grosbach741cd732011-10-17 22:26:03 +0000947 // NEON operands.
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000948 bool isVecListOneD() const {
949 if (Kind != k_VectorList) return false;
950 return VectorList.Count == 1;
951 }
952
Jim Grosbach2f2e3c42011-10-21 18:54:25 +0000953 bool isVecListTwoD() const {
954 if (Kind != k_VectorList) return false;
955 return VectorList.Count == 2;
956 }
957
Jim Grosbachc4360fe2011-10-21 20:02:19 +0000958 bool isVecListThreeD() const {
959 if (Kind != k_VectorList) return false;
960 return VectorList.Count == 3;
961 }
962
Jim Grosbach846bcff2011-10-21 20:35:01 +0000963 bool isVecListFourD() const {
964 if (Kind != k_VectorList) return false;
965 return VectorList.Count == 4;
966 }
967
Jim Grosbach118b38c2011-10-21 22:21:10 +0000968 bool isVecListTwoQ() const {
969 if (Kind != k_VectorList) return false;
970 //FIXME: We haven't taught the parser to handle by-two register lists
971 // yet, so don't pretend to know one.
972 return VectorList.Count == 2 && false;
973 }
974
Jim Grosbachcd6f5e72011-11-30 01:09:44 +0000975 bool isVecListOneDAllLanes() const {
976 if (Kind != k_VectorListAllLanes) return false;
977 return VectorList.Count == 1;
978 }
979
Jim Grosbach3ecf9762011-11-30 18:21:25 +0000980 bool isVecListTwoDAllLanes() const {
981 if (Kind != k_VectorListAllLanes) return false;
982 return VectorList.Count == 2;
983 }
984
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000985 bool isVectorIndex8() const {
986 if (Kind != k_VectorIndex) return false;
987 return VectorIndex.Val < 8;
988 }
989 bool isVectorIndex16() const {
990 if (Kind != k_VectorIndex) return false;
991 return VectorIndex.Val < 4;
992 }
993 bool isVectorIndex32() const {
994 if (Kind != k_VectorIndex) return false;
995 return VectorIndex.Val < 2;
996 }
997
Jim Grosbach741cd732011-10-17 22:26:03 +0000998 bool isNEONi8splat() const {
999 if (Kind != k_Immediate)
1000 return false;
1001 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1002 // Must be a constant.
1003 if (!CE) return false;
1004 int64_t Value = CE->getValue();
1005 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1006 // value.
Jim Grosbach741cd732011-10-17 22:26:03 +00001007 return Value >= 0 && Value < 256;
1008 }
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001009
Jim Grosbachcda32ae2011-10-17 23:09:09 +00001010 bool isNEONi16splat() const {
1011 if (Kind != k_Immediate)
1012 return false;
1013 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1014 // Must be a constant.
1015 if (!CE) return false;
1016 int64_t Value = CE->getValue();
1017 // i16 value in the range [0,255] or [0x0100, 0xff00]
1018 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1019 }
1020
Jim Grosbach8211c052011-10-18 00:22:00 +00001021 bool isNEONi32splat() const {
1022 if (Kind != k_Immediate)
1023 return false;
1024 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1025 // Must be a constant.
1026 if (!CE) return false;
1027 int64_t Value = CE->getValue();
1028 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1029 return (Value >= 0 && Value < 256) ||
1030 (Value >= 0x0100 && Value <= 0xff00) ||
1031 (Value >= 0x010000 && Value <= 0xff0000) ||
1032 (Value >= 0x01000000 && Value <= 0xff000000);
1033 }
1034
1035 bool isNEONi32vmov() const {
1036 if (Kind != k_Immediate)
1037 return false;
1038 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1039 // Must be a constant.
1040 if (!CE) return false;
1041 int64_t Value = CE->getValue();
1042 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1043 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1044 return (Value >= 0 && Value < 256) ||
1045 (Value >= 0x0100 && Value <= 0xff00) ||
1046 (Value >= 0x010000 && Value <= 0xff0000) ||
1047 (Value >= 0x01000000 && Value <= 0xff000000) ||
1048 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1049 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1050 }
1051
Jim Grosbache4454e02011-10-18 16:18:11 +00001052 bool isNEONi64splat() const {
1053 if (Kind != k_Immediate)
1054 return false;
1055 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1056 // Must be a constant.
1057 if (!CE) return false;
1058 uint64_t Value = CE->getValue();
1059 // i64 value with each byte being either 0 or 0xff.
1060 for (unsigned i = 0; i < 8; ++i)
1061 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1062 return true;
1063 }
1064
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001065 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner5d6f6a02010-10-29 00:27:31 +00001066 // Add as immediates when possible. Null MCExpr = 0.
1067 if (Expr == 0)
1068 Inst.addOperand(MCOperand::CreateImm(0));
1069 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001070 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1071 else
1072 Inst.addOperand(MCOperand::CreateExpr(Expr));
1073 }
1074
Daniel Dunbard8042b72010-08-11 06:36:53 +00001075 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001076 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbard8042b72010-08-11 06:36:53 +00001077 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach968c9272010-12-06 18:30:57 +00001078 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1079 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbard8042b72010-08-11 06:36:53 +00001080 }
1081
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001082 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1083 assert(N == 1 && "Invalid number of operands!");
1084 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1085 }
1086
Jim Grosbach48399582011-10-12 17:34:41 +00001087 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1088 assert(N == 1 && "Invalid number of operands!");
1089 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1090 }
1091
1092 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1093 assert(N == 1 && "Invalid number of operands!");
1094 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1095 }
1096
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001097 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1098 assert(N == 1 && "Invalid number of operands!");
1099 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1100 }
1101
1102 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1103 assert(N == 1 && "Invalid number of operands!");
1104 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1105 }
1106
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001107 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1108 assert(N == 1 && "Invalid number of operands!");
1109 Inst.addOperand(MCOperand::CreateReg(getReg()));
1110 }
1111
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001112 void addRegOperands(MCInst &Inst, unsigned N) const {
1113 assert(N == 1 && "Invalid number of operands!");
1114 Inst.addOperand(MCOperand::CreateReg(getReg()));
1115 }
1116
Jim Grosbachac798e12011-07-25 20:49:51 +00001117 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001118 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001119 assert(isRegShiftedReg() &&
1120 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachac798e12011-07-25 20:49:51 +00001121 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1122 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001123 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachac798e12011-07-25 20:49:51 +00001124 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001125 }
1126
Jim Grosbachac798e12011-07-25 20:49:51 +00001127 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson04912702011-07-21 23:38:37 +00001128 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001129 assert(isRegShiftedImm() &&
1130 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachac798e12011-07-25 20:49:51 +00001131 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Andersonb595ed02011-07-21 18:54:16 +00001132 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachac798e12011-07-25 20:49:51 +00001133 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Andersonb595ed02011-07-21 18:54:16 +00001134 }
1135
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001136 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001137 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001138 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1139 ShifterImm.Imm));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001140 }
1141
Bill Wendling8d2aa032010-11-08 23:49:57 +00001142 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling2cae3272010-11-09 22:44:22 +00001143 assert(N == 1 && "Invalid number of operands!");
Bill Wendlingbed94652010-11-09 23:28:44 +00001144 const SmallVectorImpl<unsigned> &RegList = getRegList();
1145 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00001146 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1147 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling8d2aa032010-11-08 23:49:57 +00001148 }
1149
Bill Wendling9898ac92010-11-17 04:32:08 +00001150 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1151 addRegListOperands(Inst, N);
1152 }
1153
1154 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1155 addRegListOperands(Inst, N);
1156 }
1157
Jim Grosbach833b9d32011-07-27 20:15:40 +00001158 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1159 assert(N == 1 && "Invalid number of operands!");
1160 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1161 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1162 }
1163
Jim Grosbach864b6092011-07-28 21:34:26 +00001164 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1165 assert(N == 1 && "Invalid number of operands!");
1166 // Munge the lsb/width into a bitfield mask.
1167 unsigned lsb = Bitfield.LSB;
1168 unsigned width = Bitfield.Width;
1169 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1170 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1171 (32 - (lsb + width)));
1172 Inst.addOperand(MCOperand::CreateImm(Mask));
1173 }
1174
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001175 void addImmOperands(MCInst &Inst, unsigned N) const {
1176 assert(N == 1 && "Invalid number of operands!");
1177 addExpr(Inst, getImm());
1178 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00001179
Jim Grosbache7fbce72011-10-03 23:38:36 +00001180 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1181 assert(N == 1 && "Invalid number of operands!");
1182 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1183 }
1184
Jim Grosbach7db8d692011-09-08 22:07:06 +00001185 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1186 assert(N == 1 && "Invalid number of operands!");
1187 // FIXME: We really want to scale the value here, but the LDRD/STRD
1188 // instruction don't encode operands that way yet.
1189 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1190 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1191 }
1192
Jim Grosbach0a0b3072011-08-24 21:22:15 +00001193 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1194 assert(N == 1 && "Invalid number of operands!");
1195 // The immediate is scaled by four in the encoding and is stored
1196 // in the MCInst as such. Lop off the low two bits here.
1197 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1198 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1199 }
1200
1201 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1202 assert(N == 1 && "Invalid number of operands!");
1203 // The immediate is scaled by four in the encoding and is stored
1204 // in the MCInst as such. Lop off the low two bits here.
1205 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1206 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1207 }
1208
Jim Grosbach475c6db2011-07-25 23:09:14 +00001209 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1210 assert(N == 1 && "Invalid number of operands!");
1211 // The constant encodes as the immediate-1, and we store in the instruction
1212 // the bits as encoded, so subtract off one here.
1213 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1214 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1215 }
1216
Jim Grosbach801e0a32011-07-22 23:16:18 +00001217 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1218 assert(N == 1 && "Invalid number of operands!");
1219 // The constant encodes as the immediate-1, and we store in the instruction
1220 // the bits as encoded, so subtract off one here.
1221 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1222 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1223 }
1224
Jim Grosbach46dd4132011-08-17 21:51:27 +00001225 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1226 assert(N == 1 && "Invalid number of operands!");
1227 // The constant encodes as the immediate, except for 32, which encodes as
1228 // zero.
1229 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1230 unsigned Imm = CE->getValue();
1231 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1232 }
1233
Jim Grosbach27c1e252011-07-21 17:23:04 +00001234 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1235 assert(N == 1 && "Invalid number of operands!");
1236 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1237 // the instruction as well.
1238 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1239 int Val = CE->getValue();
1240 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1241 }
1242
Jim Grosbachb009a872011-10-28 22:36:30 +00001243 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1244 assert(N == 1 && "Invalid number of operands!");
1245 // The operand is actually a t2_so_imm, but we have its bitwise
1246 // negation in the assembly source, so twiddle it here.
1247 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1248 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1249 }
1250
Jim Grosbach3d785ed2011-10-28 22:50:54 +00001251 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1252 assert(N == 1 && "Invalid number of operands!");
1253 // The operand is actually a so_imm, but we have its bitwise
1254 // negation in the assembly source, so twiddle it here.
1255 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1256 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1257 }
1258
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001259 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1260 assert(N == 1 && "Invalid number of operands!");
1261 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1262 }
1263
Jim Grosbachd3595712011-08-03 23:50:40 +00001264 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1265 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001266 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopesf170f8b2011-03-24 21:04:58 +00001267 }
1268
Jim Grosbacha95ec992011-10-11 17:29:55 +00001269 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1270 assert(N == 2 && "Invalid number of operands!");
1271 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1272 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1273 }
1274
Jim Grosbachd3595712011-08-03 23:50:40 +00001275 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1276 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001277 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1278 if (!Memory.OffsetRegNum) {
Jim Grosbachd3595712011-08-03 23:50:40 +00001279 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1280 // Special case for #-0
1281 if (Val == INT32_MIN) Val = 0;
1282 if (Val < 0) Val = -Val;
1283 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1284 } else {
1285 // For register offset, we encode the shift type and negation flag
1286 // here.
Jim Grosbach871dff72011-10-11 15:59:20 +00001287 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1288 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001289 }
Jim Grosbach871dff72011-10-11 15:59:20 +00001290 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1291 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001292 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001293 }
1294
Jim Grosbachcd17c122011-08-04 23:01:30 +00001295 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1296 assert(N == 2 && "Invalid number of operands!");
1297 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1298 assert(CE && "non-constant AM2OffsetImm operand!");
1299 int32_t Val = CE->getValue();
1300 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1301 // Special case for #-0
1302 if (Val == INT32_MIN) Val = 0;
1303 if (Val < 0) Val = -Val;
1304 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1305 Inst.addOperand(MCOperand::CreateReg(0));
1306 Inst.addOperand(MCOperand::CreateImm(Val));
1307 }
1308
Jim Grosbach5b96b802011-08-10 20:29:19 +00001309 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1310 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001311 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1312 if (!Memory.OffsetRegNum) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00001313 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1314 // Special case for #-0
1315 if (Val == INT32_MIN) Val = 0;
1316 if (Val < 0) Val = -Val;
1317 Val = ARM_AM::getAM3Opc(AddSub, Val);
1318 } else {
1319 // For register offset, we encode the shift type and negation flag
1320 // here.
Jim Grosbach871dff72011-10-11 15:59:20 +00001321 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach5b96b802011-08-10 20:29:19 +00001322 }
Jim Grosbach871dff72011-10-11 15:59:20 +00001323 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1324 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach5b96b802011-08-10 20:29:19 +00001325 Inst.addOperand(MCOperand::CreateImm(Val));
1326 }
1327
1328 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1329 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001330 if (Kind == k_PostIndexRegister) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00001331 int32_t Val =
1332 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1333 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1334 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001335 return;
Jim Grosbach5b96b802011-08-10 20:29:19 +00001336 }
1337
1338 // Constant offset.
1339 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1340 int32_t Val = CE->getValue();
1341 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1342 // Special case for #-0
1343 if (Val == INT32_MIN) Val = 0;
1344 if (Val < 0) Val = -Val;
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001345 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach5b96b802011-08-10 20:29:19 +00001346 Inst.addOperand(MCOperand::CreateReg(0));
1347 Inst.addOperand(MCOperand::CreateImm(Val));
1348 }
1349
Jim Grosbachd3595712011-08-03 23:50:40 +00001350 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1351 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachfb2f1d62011-11-01 01:24:45 +00001352 // If we have an immediate that's not a constant, treat it as a label
1353 // reference needing a fixup. If it is a constant, it's something else
1354 // and we reject it.
1355 if (isImm()) {
1356 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1357 Inst.addOperand(MCOperand::CreateImm(0));
1358 return;
1359 }
1360
Jim Grosbachd3595712011-08-03 23:50:40 +00001361 // The lower two bits are always zero and as such are not encoded.
Jim Grosbach871dff72011-10-11 15:59:20 +00001362 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00001363 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1364 // Special case for #-0
1365 if (Val == INT32_MIN) Val = 0;
1366 if (Val < 0) Val = -Val;
1367 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbach871dff72011-10-11 15:59:20 +00001368 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001369 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00001370 }
1371
Jim Grosbach7db8d692011-09-08 22:07:06 +00001372 void addMemImm8s4OffsetOperands(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 Grosbach7db8d692011-09-08 22:07:06 +00001376 Inst.addOperand(MCOperand::CreateImm(Val));
1377 }
1378
Jim Grosbacha05627e2011-09-09 18:37:27 +00001379 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1380 assert(N == 2 && "Invalid number of operands!");
1381 // The lower two bits are always zero and as such are not encoded.
Jim Grosbach871dff72011-10-11 15:59:20 +00001382 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1383 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha05627e2011-09-09 18:37:27 +00001384 Inst.addOperand(MCOperand::CreateImm(Val));
1385 }
1386
Jim Grosbachd3595712011-08-03 23:50:40 +00001387 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1388 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001389 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1390 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001391 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner5d6f6a02010-10-29 00:27:31 +00001392 }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001393
Jim Grosbach2392c532011-09-07 23:39:14 +00001394 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1395 addMemImm8OffsetOperands(Inst, N);
1396 }
1397
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001398 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach2392c532011-09-07 23:39:14 +00001399 addMemImm8OffsetOperands(Inst, N);
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001400 }
1401
1402 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1403 assert(N == 2 && "Invalid number of operands!");
1404 // If this is an immediate, it's a label reference.
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001405 if (Kind == k_Immediate) {
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +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 Grosbach5bfa8ba2011-09-07 20:58:57 +00001414 Inst.addOperand(MCOperand::CreateImm(Val));
1415 }
1416
Jim Grosbachd3595712011-08-03 23:50:40 +00001417 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1418 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach95466ce2011-08-08 20:59:31 +00001419 // If this is an immediate, it's a label reference.
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001420 if (Kind == k_Immediate) {
Jim Grosbach95466ce2011-08-08 20:59:31 +00001421 addExpr(Inst, getImm());
1422 Inst.addOperand(MCOperand::CreateImm(0));
1423 return;
1424 }
1425
1426 // Otherwise, it's a normal memory reg+offset.
Jim Grosbach871dff72011-10-11 15:59:20 +00001427 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1428 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001429 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendling092a7bd2010-12-14 03:36:38 +00001430 }
Bill Wendling811c9362010-11-30 07:44:32 +00001431
Jim Grosbach05541f42011-09-19 22:21:13 +00001432 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1433 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001434 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1435 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach05541f42011-09-19 22:21:13 +00001436 }
1437
1438 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1439 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001440 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1441 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach05541f42011-09-19 22:21:13 +00001442 }
1443
Jim Grosbachd3595712011-08-03 23:50:40 +00001444 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1445 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001446 unsigned Val =
1447 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1448 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbach871dff72011-10-11 15:59:20 +00001449 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1450 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001451 Inst.addOperand(MCOperand::CreateImm(Val));
1452 }
1453
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001454 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1455 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001456 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1457 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1458 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001459 }
1460
Jim Grosbachd3595712011-08-03 23:50:40 +00001461 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1462 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001463 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1464 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001465 }
1466
Jim Grosbach3fe94e32011-08-19 17:55:24 +00001467 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1468 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001469 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1470 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach3fe94e32011-08-19 17:55:24 +00001471 Inst.addOperand(MCOperand::CreateImm(Val));
1472 }
1473
Jim Grosbach26d35872011-08-19 18:55:51 +00001474 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1475 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001476 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1477 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach26d35872011-08-19 18:55:51 +00001478 Inst.addOperand(MCOperand::CreateImm(Val));
1479 }
1480
Jim Grosbacha32c7532011-08-19 18:49:59 +00001481 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1482 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001483 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1484 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha32c7532011-08-19 18:49:59 +00001485 Inst.addOperand(MCOperand::CreateImm(Val));
1486 }
1487
Jim Grosbach23983d62011-08-19 18:13:48 +00001488 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1489 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001490 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1491 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach23983d62011-08-19 18:13:48 +00001492 Inst.addOperand(MCOperand::CreateImm(Val));
1493 }
1494
Jim Grosbachd3595712011-08-03 23:50:40 +00001495 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1496 assert(N == 1 && "Invalid number of operands!");
1497 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1498 assert(CE && "non-constant post-idx-imm8 operand!");
1499 int Imm = CE->getValue();
1500 bool isAdd = Imm >= 0;
Owen Andersonf02d98d2011-08-29 17:17:09 +00001501 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00001502 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1503 Inst.addOperand(MCOperand::CreateImm(Imm));
1504 }
1505
Jim Grosbach93981412011-10-11 21:55:36 +00001506 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1507 assert(N == 1 && "Invalid number of operands!");
1508 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1509 assert(CE && "non-constant post-idx-imm8s4 operand!");
1510 int Imm = CE->getValue();
1511 bool isAdd = Imm >= 0;
1512 if (Imm == INT32_MIN) Imm = 0;
1513 // Immediate is scaled by 4.
1514 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1515 Inst.addOperand(MCOperand::CreateImm(Imm));
1516 }
1517
Jim Grosbachd3595712011-08-03 23:50:40 +00001518 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1519 assert(N == 2 && "Invalid number of operands!");
1520 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachc320c852011-08-05 21:28:30 +00001521 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1522 }
1523
1524 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1525 assert(N == 2 && "Invalid number of operands!");
1526 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1527 // The sign, shift type, and shift amount are encoded in a single operand
1528 // using the AM2 encoding helpers.
1529 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1530 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1531 PostIdxReg.ShiftTy);
1532 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendling811c9362010-11-30 07:44:32 +00001533 }
1534
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001535 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1536 assert(N == 1 && "Invalid number of operands!");
1537 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1538 }
1539
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001540 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1541 assert(N == 1 && "Invalid number of operands!");
1542 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1543 }
1544
Jim Grosbach182b6a02011-11-29 23:51:09 +00001545 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001546 assert(N == 1 && "Invalid number of operands!");
1547 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1548 }
1549
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001550 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1551 assert(N == 1 && "Invalid number of operands!");
1552 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1553 }
1554
1555 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1556 assert(N == 1 && "Invalid number of operands!");
1557 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1558 }
1559
1560 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1561 assert(N == 1 && "Invalid number of operands!");
1562 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1563 }
1564
Jim Grosbach741cd732011-10-17 22:26:03 +00001565 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1566 assert(N == 1 && "Invalid number of operands!");
1567 // The immediate encodes the type of constant as well as the value.
1568 // Mask in that this is an i8 splat.
1569 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1570 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1571 }
1572
Jim Grosbachcda32ae2011-10-17 23:09:09 +00001573 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1574 assert(N == 1 && "Invalid number of operands!");
1575 // The immediate encodes the type of constant as well as the value.
1576 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1577 unsigned Value = CE->getValue();
1578 if (Value >= 256)
1579 Value = (Value >> 8) | 0xa00;
1580 else
1581 Value |= 0x800;
1582 Inst.addOperand(MCOperand::CreateImm(Value));
1583 }
1584
Jim Grosbach8211c052011-10-18 00:22:00 +00001585 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1586 assert(N == 1 && "Invalid number of operands!");
1587 // The immediate encodes the type of constant as well as the value.
1588 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1589 unsigned Value = CE->getValue();
1590 if (Value >= 256 && Value <= 0xff00)
1591 Value = (Value >> 8) | 0x200;
1592 else if (Value > 0xffff && Value <= 0xff0000)
1593 Value = (Value >> 16) | 0x400;
1594 else if (Value > 0xffffff)
1595 Value = (Value >> 24) | 0x600;
1596 Inst.addOperand(MCOperand::CreateImm(Value));
1597 }
1598
1599 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1600 assert(N == 1 && "Invalid number of operands!");
1601 // The immediate encodes the type of constant as well as the value.
1602 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1603 unsigned Value = CE->getValue();
1604 if (Value >= 256 && Value <= 0xffff)
1605 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1606 else if (Value > 0xffff && Value <= 0xffffff)
1607 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1608 else if (Value > 0xffffff)
1609 Value = (Value >> 24) | 0x600;
1610 Inst.addOperand(MCOperand::CreateImm(Value));
1611 }
1612
Jim Grosbache4454e02011-10-18 16:18:11 +00001613 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1614 assert(N == 1 && "Invalid number of operands!");
1615 // The immediate encodes the type of constant as well as the value.
1616 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1617 uint64_t Value = CE->getValue();
1618 unsigned Imm = 0;
1619 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1620 Imm |= (Value & 1) << i;
1621 }
1622 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1623 }
1624
Jim Grosbach602aa902011-07-13 15:34:57 +00001625 virtual void print(raw_ostream &OS) const;
Daniel Dunbarebace222010-08-11 06:37:04 +00001626
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001627 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001628 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001629 Op->ITMask.Mask = Mask;
1630 Op->StartLoc = S;
1631 Op->EndLoc = S;
1632 return Op;
1633 }
1634
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001635 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001636 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001637 Op->CC.Val = CC;
1638 Op->StartLoc = S;
1639 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001640 return Op;
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001641 }
1642
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001643 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001644 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001645 Op->Cop.Val = CopVal;
1646 Op->StartLoc = S;
1647 Op->EndLoc = S;
1648 return Op;
1649 }
1650
1651 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001652 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001653 Op->Cop.Val = CopVal;
1654 Op->StartLoc = S;
1655 Op->EndLoc = S;
1656 return Op;
1657 }
1658
Jim Grosbach48399582011-10-12 17:34:41 +00001659 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1660 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1661 Op->Cop.Val = Val;
1662 Op->StartLoc = S;
1663 Op->EndLoc = E;
1664 return Op;
1665 }
1666
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001667 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001668 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001669 Op->Reg.RegNum = RegNum;
1670 Op->StartLoc = S;
1671 Op->EndLoc = S;
1672 return Op;
1673 }
1674
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001675 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001676 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001677 Op->Tok.Data = Str.data();
1678 Op->Tok.Length = Str.size();
1679 Op->StartLoc = S;
1680 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001681 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001682 }
1683
Bill Wendling2063b842010-11-18 23:43:05 +00001684 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001685 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001686 Op->Reg.RegNum = RegNum;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001687 Op->StartLoc = S;
1688 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001689 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001690 }
1691
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001692 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1693 unsigned SrcReg,
1694 unsigned ShiftReg,
1695 unsigned ShiftImm,
1696 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001697 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachac798e12011-07-25 20:49:51 +00001698 Op->RegShiftedReg.ShiftTy = ShTy;
1699 Op->RegShiftedReg.SrcReg = SrcReg;
1700 Op->RegShiftedReg.ShiftReg = ShiftReg;
1701 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001702 Op->StartLoc = S;
1703 Op->EndLoc = E;
1704 return Op;
1705 }
1706
Owen Andersonb595ed02011-07-21 18:54:16 +00001707 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1708 unsigned SrcReg,
1709 unsigned ShiftImm,
1710 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001711 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachac798e12011-07-25 20:49:51 +00001712 Op->RegShiftedImm.ShiftTy = ShTy;
1713 Op->RegShiftedImm.SrcReg = SrcReg;
1714 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Andersonb595ed02011-07-21 18:54:16 +00001715 Op->StartLoc = S;
1716 Op->EndLoc = E;
1717 return Op;
1718 }
1719
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001720 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001721 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001722 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001723 Op->ShifterImm.isASR = isASR;
1724 Op->ShifterImm.Imm = Imm;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001725 Op->StartLoc = S;
1726 Op->EndLoc = E;
1727 return Op;
1728 }
1729
Jim Grosbach833b9d32011-07-27 20:15:40 +00001730 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001731 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach833b9d32011-07-27 20:15:40 +00001732 Op->RotImm.Imm = Imm;
1733 Op->StartLoc = S;
1734 Op->EndLoc = E;
1735 return Op;
1736 }
1737
Jim Grosbach864b6092011-07-28 21:34:26 +00001738 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1739 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001740 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach864b6092011-07-28 21:34:26 +00001741 Op->Bitfield.LSB = LSB;
1742 Op->Bitfield.Width = Width;
1743 Op->StartLoc = S;
1744 Op->EndLoc = E;
1745 return Op;
1746 }
1747
Bill Wendling2cae3272010-11-09 22:44:22 +00001748 static ARMOperand *
Bill Wendlingbed94652010-11-09 23:28:44 +00001749 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00001750 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001751 KindTy Kind = k_RegisterList;
Bill Wendling9898ac92010-11-17 04:32:08 +00001752
Jim Grosbach75461af2011-09-13 22:56:44 +00001753 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001754 Kind = k_DPRRegisterList;
Jim Grosbach75461af2011-09-13 22:56:44 +00001755 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng9eec7642011-07-25 21:32:49 +00001756 contains(Regs.front().first))
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001757 Kind = k_SPRRegisterList;
Bill Wendling9898ac92010-11-17 04:32:08 +00001758
1759 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendlingbed94652010-11-09 23:28:44 +00001760 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00001761 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling0ab0f672010-11-18 21:50:54 +00001762 Op->Registers.push_back(I->first);
Bill Wendling20b5ea982010-11-19 00:38:19 +00001763 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00001764 Op->StartLoc = StartLoc;
1765 Op->EndLoc = EndLoc;
Bill Wendling7cef4472010-11-06 19:56:04 +00001766 return Op;
1767 }
1768
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001769 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
1770 SMLoc S, SMLoc E) {
1771 ARMOperand *Op = new ARMOperand(k_VectorList);
1772 Op->VectorList.RegNum = RegNum;
1773 Op->VectorList.Count = Count;
1774 Op->StartLoc = S;
1775 Op->EndLoc = E;
1776 return Op;
1777 }
1778
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00001779 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
1780 SMLoc S, SMLoc E) {
1781 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
1782 Op->VectorList.RegNum = RegNum;
1783 Op->VectorList.Count = Count;
1784 Op->StartLoc = S;
1785 Op->EndLoc = E;
1786 return Op;
1787 }
1788
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001789 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
1790 MCContext &Ctx) {
1791 ARMOperand *Op = new ARMOperand(k_VectorIndex);
1792 Op->VectorIndex.Val = Idx;
1793 Op->StartLoc = S;
1794 Op->EndLoc = E;
1795 return Op;
1796 }
1797
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001798 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001799 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001800 Op->Imm.Val = Val;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001801 Op->StartLoc = S;
1802 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001803 return Op;
Kevin Enderbyf5079942009-10-13 22:19:02 +00001804 }
1805
Jim Grosbache7fbce72011-10-03 23:38:36 +00001806 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001807 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbache7fbce72011-10-03 23:38:36 +00001808 Op->FPImm.Val = Val;
1809 Op->StartLoc = S;
1810 Op->EndLoc = S;
1811 return Op;
1812 }
1813
Jim Grosbachd3595712011-08-03 23:50:40 +00001814 static ARMOperand *CreateMem(unsigned BaseRegNum,
1815 const MCConstantExpr *OffsetImm,
1816 unsigned OffsetRegNum,
1817 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00001818 unsigned ShiftImm,
Jim Grosbacha95ec992011-10-11 17:29:55 +00001819 unsigned Alignment,
Jim Grosbachd3595712011-08-03 23:50:40 +00001820 bool isNegative,
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001821 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001822 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbach871dff72011-10-11 15:59:20 +00001823 Op->Memory.BaseRegNum = BaseRegNum;
1824 Op->Memory.OffsetImm = OffsetImm;
1825 Op->Memory.OffsetRegNum = OffsetRegNum;
1826 Op->Memory.ShiftType = ShiftType;
1827 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbacha95ec992011-10-11 17:29:55 +00001828 Op->Memory.Alignment = Alignment;
Jim Grosbach871dff72011-10-11 15:59:20 +00001829 Op->Memory.isNegative = isNegative;
Jim Grosbachd3595712011-08-03 23:50:40 +00001830 Op->StartLoc = S;
1831 Op->EndLoc = E;
1832 return Op;
1833 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00001834
Jim Grosbachc320c852011-08-05 21:28:30 +00001835 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
1836 ARM_AM::ShiftOpc ShiftTy,
1837 unsigned ShiftImm,
Jim Grosbachd3595712011-08-03 23:50:40 +00001838 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001839 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbachd3595712011-08-03 23:50:40 +00001840 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachc320c852011-08-05 21:28:30 +00001841 Op->PostIdxReg.isAdd = isAdd;
1842 Op->PostIdxReg.ShiftTy = ShiftTy;
1843 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001844 Op->StartLoc = S;
1845 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001846 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001847 }
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001848
1849 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001850 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001851 Op->MBOpt.Val = Opt;
1852 Op->StartLoc = S;
1853 Op->EndLoc = S;
1854 return Op;
1855 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001856
1857 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001858 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001859 Op->IFlags.Val = IFlags;
1860 Op->StartLoc = S;
1861 Op->EndLoc = S;
1862 return Op;
1863 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001864
1865 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001866 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001867 Op->MMask.Val = MMask;
1868 Op->StartLoc = S;
1869 Op->EndLoc = S;
1870 return Op;
1871 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001872};
1873
1874} // end anonymous namespace.
1875
Jim Grosbach602aa902011-07-13 15:34:57 +00001876void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001877 switch (Kind) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001878 case k_FPImmediate:
Jim Grosbache7fbce72011-10-03 23:38:36 +00001879 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
1880 << ") >";
1881 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001882 case k_CondCode:
Daniel Dunbar2be732a2011-01-10 15:26:21 +00001883 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001884 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001885 case k_CCOut:
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001886 OS << "<ccout " << getReg() << ">";
1887 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001888 case k_ITCondMask: {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00001889 static const char *MaskStr[] = {
1890 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
1891 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
1892 };
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001893 assert((ITMask.Mask & 0xf) == ITMask.Mask);
1894 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
1895 break;
1896 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001897 case k_CoprocNum:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001898 OS << "<coprocessor number: " << getCoproc() << ">";
1899 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001900 case k_CoprocReg:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001901 OS << "<coprocessor register: " << getCoproc() << ">";
1902 break;
Jim Grosbach48399582011-10-12 17:34:41 +00001903 case k_CoprocOption:
1904 OS << "<coprocessor option: " << CoprocOption.Val << ">";
1905 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001906 case k_MSRMask:
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001907 OS << "<mask: " << getMSRMask() << ">";
1908 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001909 case k_Immediate:
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001910 getImm()->print(OS);
1911 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001912 case k_MemBarrierOpt:
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001913 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
1914 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001915 case k_Memory:
Daniel Dunbarbcd8eb02011-01-18 05:55:21 +00001916 OS << "<memory "
Jim Grosbach871dff72011-10-11 15:59:20 +00001917 << " base:" << Memory.BaseRegNum;
Daniel Dunbarbcd8eb02011-01-18 05:55:21 +00001918 OS << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001919 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001920 case k_PostIndexRegister:
Jim Grosbachc320c852011-08-05 21:28:30 +00001921 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
1922 << PostIdxReg.RegNum;
1923 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
1924 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
1925 << PostIdxReg.ShiftImm;
1926 OS << ">";
Jim Grosbachd3595712011-08-03 23:50:40 +00001927 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001928 case k_ProcIFlags: {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001929 OS << "<ARM_PROC::";
1930 unsigned IFlags = getProcIFlags();
1931 for (int i=2; i >= 0; --i)
1932 if (IFlags & (1 << i))
1933 OS << ARM_PROC::IFlagsToString(1 << i);
1934 OS << ">";
1935 break;
1936 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001937 case k_Register:
Bill Wendling2063b842010-11-18 23:43:05 +00001938 OS << "<register " << getReg() << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001939 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001940 case k_ShifterImmediate:
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001941 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
1942 << " #" << ShifterImm.Imm << ">";
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001943 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001944 case k_ShiftedRegister:
Owen Andersonb595ed02011-07-21 18:54:16 +00001945 OS << "<so_reg_reg "
Jim Grosbach01e04392011-11-16 21:46:50 +00001946 << RegShiftedReg.SrcReg << " "
1947 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
1948 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001949 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001950 case k_ShiftedImmediate:
Owen Andersonb595ed02011-07-21 18:54:16 +00001951 OS << "<so_reg_imm "
Jim Grosbach01e04392011-11-16 21:46:50 +00001952 << RegShiftedImm.SrcReg << " "
1953 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
1954 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Andersonb595ed02011-07-21 18:54:16 +00001955 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001956 case k_RotateImmediate:
Jim Grosbach833b9d32011-07-27 20:15:40 +00001957 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
1958 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001959 case k_BitfieldDescriptor:
Jim Grosbach864b6092011-07-28 21:34:26 +00001960 OS << "<bitfield " << "lsb: " << Bitfield.LSB
1961 << ", width: " << Bitfield.Width << ">";
1962 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001963 case k_RegisterList:
1964 case k_DPRRegisterList:
1965 case k_SPRRegisterList: {
Bill Wendling7cef4472010-11-06 19:56:04 +00001966 OS << "<register_list ";
Bill Wendling7cef4472010-11-06 19:56:04 +00001967
Bill Wendlingbed94652010-11-09 23:28:44 +00001968 const SmallVectorImpl<unsigned> &RegList = getRegList();
1969 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00001970 I = RegList.begin(), E = RegList.end(); I != E; ) {
1971 OS << *I;
1972 if (++I < E) OS << ", ";
Bill Wendling7cef4472010-11-06 19:56:04 +00001973 }
1974
1975 OS << ">";
1976 break;
1977 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001978 case k_VectorList:
1979 OS << "<vector_list " << VectorList.Count << " * "
1980 << VectorList.RegNum << ">";
1981 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00001982 case k_VectorListAllLanes:
1983 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
1984 << VectorList.RegNum << ">";
1985 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001986 case k_Token:
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001987 OS << "'" << getToken() << "'";
1988 break;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001989 case k_VectorIndex:
1990 OS << "<vectorindex " << getVectorIndex() << ">";
1991 break;
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001992 }
1993}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001994
1995/// @name Auto-generated Match Functions
1996/// {
1997
1998static unsigned MatchRegisterName(StringRef Name);
1999
2000/// }
2001
Bob Wilsonfb0bd042011-02-03 21:46:10 +00002002bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2003 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002004 RegNo = tryParseRegister();
Roman Divacky36b1b472011-01-27 17:14:22 +00002005
2006 return (RegNo == (unsigned)-1);
2007}
2008
Kevin Enderby8be42bd2009-10-30 22:55:57 +00002009/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattner44e5981c2010-10-30 04:09:10 +00002010/// and if it is a register name the token is eaten and the register number is
2011/// returned. Otherwise return -1.
2012///
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002013int ARMAsmParser::tryParseRegister() {
Chris Lattner44e5981c2010-10-30 04:09:10 +00002014 const AsmToken &Tok = Parser.getTok();
Jim Grosbachd3595712011-08-03 23:50:40 +00002015 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbach99710a82010-11-01 16:44:21 +00002016
Chris Lattner44e5981c2010-10-30 04:09:10 +00002017 // FIXME: Validate register for the current architecture; we have to do
2018 // validation later, so maybe there is no need for this here.
Benjamin Kramer20baffb2011-11-06 20:37:06 +00002019 std::string lowerCase = Tok.getString().lower();
Owen Andersona098d152011-01-13 22:50:36 +00002020 unsigned RegNum = MatchRegisterName(lowerCase);
2021 if (!RegNum) {
2022 RegNum = StringSwitch<unsigned>(lowerCase)
2023 .Case("r13", ARM::SP)
2024 .Case("r14", ARM::LR)
2025 .Case("r15", ARM::PC)
2026 .Case("ip", ARM::R12)
2027 .Default(0);
2028 }
2029 if (!RegNum) return -1;
Bob Wilsonfb0bd042011-02-03 21:46:10 +00002030
Chris Lattner44e5981c2010-10-30 04:09:10 +00002031 Parser.Lex(); // Eat identifier token.
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002032
Chris Lattner44e5981c2010-10-30 04:09:10 +00002033 return RegNum;
2034}
Jim Grosbach99710a82010-11-01 16:44:21 +00002035
Jim Grosbachbb24c592011-07-13 18:49:30 +00002036// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2037// If a recoverable error occurs, return 1. If an irrecoverable error
2038// occurs, return -1. An irrecoverable error is one where tokens have been
2039// consumed in the process of trying to parse the shifter (i.e., when it is
2040// indeed a shifter operand, but malformed).
Jim Grosbach0d6022d2011-07-26 20:41:24 +00002041int ARMAsmParser::tryParseShiftRegister(
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002042 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2043 SMLoc S = Parser.getTok().getLoc();
2044 const AsmToken &Tok = Parser.getTok();
2045 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2046
Benjamin Kramer20baffb2011-11-06 20:37:06 +00002047 std::string lowerCase = Tok.getString().lower();
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002048 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
2049 .Case("lsl", ARM_AM::lsl)
2050 .Case("lsr", ARM_AM::lsr)
2051 .Case("asr", ARM_AM::asr)
2052 .Case("ror", ARM_AM::ror)
2053 .Case("rrx", ARM_AM::rrx)
2054 .Default(ARM_AM::no_shift);
2055
2056 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbachbb24c592011-07-13 18:49:30 +00002057 return 1;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002058
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002059 Parser.Lex(); // Eat the operator.
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002060
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002061 // The source register for the shift has already been added to the
2062 // operand list, so we need to pop it off and combine it into the shifted
2063 // register operand instead.
Benjamin Kramer1757e7a2011-07-14 18:41:22 +00002064 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002065 if (!PrevOp->isReg())
2066 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2067 int SrcReg = PrevOp->getReg();
2068 int64_t Imm = 0;
2069 int ShiftReg = 0;
2070 if (ShiftTy == ARM_AM::rrx) {
2071 // RRX Doesn't have an explicit shift amount. The encoder expects
2072 // the shift register to be the same as the source register. Seems odd,
2073 // but OK.
2074 ShiftReg = SrcReg;
2075 } else {
2076 // Figure out if this is shifted by a constant or a register (for non-RRX).
2077 if (Parser.getTok().is(AsmToken::Hash)) {
2078 Parser.Lex(); // Eat hash.
2079 SMLoc ImmLoc = Parser.getTok().getLoc();
2080 const MCExpr *ShiftExpr = 0;
Jim Grosbachbb24c592011-07-13 18:49:30 +00002081 if (getParser().ParseExpression(ShiftExpr)) {
2082 Error(ImmLoc, "invalid immediate shift value");
2083 return -1;
2084 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002085 // The expression must be evaluatable as an immediate.
2086 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbachbb24c592011-07-13 18:49:30 +00002087 if (!CE) {
2088 Error(ImmLoc, "invalid immediate shift value");
2089 return -1;
2090 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002091 // Range check the immediate.
2092 // lsl, ror: 0 <= imm <= 31
2093 // lsr, asr: 0 <= imm <= 32
2094 Imm = CE->getValue();
2095 if (Imm < 0 ||
2096 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2097 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbachbb24c592011-07-13 18:49:30 +00002098 Error(ImmLoc, "immediate shift value out of range");
2099 return -1;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002100 }
2101 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002102 ShiftReg = tryParseRegister();
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002103 SMLoc L = Parser.getTok().getLoc();
Jim Grosbachbb24c592011-07-13 18:49:30 +00002104 if (ShiftReg == -1) {
2105 Error (L, "expected immediate or register in shift operand");
2106 return -1;
2107 }
2108 } else {
2109 Error (Parser.getTok().getLoc(),
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002110 "expected immediate or register in shift operand");
Jim Grosbachbb24c592011-07-13 18:49:30 +00002111 return -1;
2112 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002113 }
2114
Owen Andersonb595ed02011-07-21 18:54:16 +00002115 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2116 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachac798e12011-07-25 20:49:51 +00002117 ShiftReg, Imm,
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002118 S, Parser.getTok().getLoc()));
Owen Andersonb595ed02011-07-21 18:54:16 +00002119 else
2120 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2121 S, Parser.getTok().getLoc()));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002122
Jim Grosbachbb24c592011-07-13 18:49:30 +00002123 return 0;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002124}
2125
2126
Bill Wendling2063b842010-11-18 23:43:05 +00002127/// Try to parse a register name. The token must be an Identifier when called.
2128/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2129/// if there is a "writeback". 'true' if it's not a register.
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002130///
Kevin Enderby8be42bd2009-10-30 22:55:57 +00002131/// TODO this is likely to change to allow different register types and or to
2132/// parse for a specific register type.
Bill Wendling2063b842010-11-18 23:43:05 +00002133bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002134tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattner44e5981c2010-10-30 04:09:10 +00002135 SMLoc S = Parser.getTok().getLoc();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002136 int RegNo = tryParseRegister();
Bill Wendlinge18980a2010-11-06 22:36:58 +00002137 if (RegNo == -1)
Bill Wendling2063b842010-11-18 23:43:05 +00002138 return true;
Jim Grosbach99710a82010-11-01 16:44:21 +00002139
Bill Wendling2063b842010-11-18 23:43:05 +00002140 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002141
Chris Lattner44e5981c2010-10-30 04:09:10 +00002142 const AsmToken &ExclaimTok = Parser.getTok();
2143 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling2063b842010-11-18 23:43:05 +00002144 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2145 ExclaimTok.getLoc()));
Chris Lattner44e5981c2010-10-30 04:09:10 +00002146 Parser.Lex(); // Eat exclaim token
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002147 return false;
2148 }
2149
2150 // Also check for an index operand. This is only legal for vector registers,
2151 // but that'll get caught OK in operand matching, so we don't need to
2152 // explicitly filter everything else out here.
2153 if (Parser.getTok().is(AsmToken::LBrac)) {
2154 SMLoc SIdx = Parser.getTok().getLoc();
2155 Parser.Lex(); // Eat left bracket token.
2156
2157 const MCExpr *ImmVal;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002158 if (getParser().ParseExpression(ImmVal))
2159 return MatchOperand_ParseFail;
2160 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2161 if (!MCE) {
2162 TokError("immediate value expected for vector index");
2163 return MatchOperand_ParseFail;
2164 }
2165
2166 SMLoc E = Parser.getTok().getLoc();
2167 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2168 Error(E, "']' expected");
2169 return MatchOperand_ParseFail;
2170 }
2171
2172 Parser.Lex(); // Eat right bracket token.
2173
2174 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2175 SIdx, E,
2176 getContext()));
Kevin Enderby2207e5f2009-10-07 18:01:35 +00002177 }
2178
Bill Wendling2063b842010-11-18 23:43:05 +00002179 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002180}
2181
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002182/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2183/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2184/// "c5", ...
2185static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002186 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2187 // but efficient.
2188 switch (Name.size()) {
2189 default: break;
2190 case 2:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002191 if (Name[0] != CoprocOp)
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002192 return -1;
2193 switch (Name[1]) {
2194 default: return -1;
2195 case '0': return 0;
2196 case '1': return 1;
2197 case '2': return 2;
2198 case '3': return 3;
2199 case '4': return 4;
2200 case '5': return 5;
2201 case '6': return 6;
2202 case '7': return 7;
2203 case '8': return 8;
2204 case '9': return 9;
2205 }
2206 break;
2207 case 3:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002208 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002209 return -1;
2210 switch (Name[2]) {
2211 default: return -1;
2212 case '0': return 10;
2213 case '1': return 11;
2214 case '2': return 12;
2215 case '3': return 13;
2216 case '4': return 14;
2217 case '5': return 15;
2218 }
2219 break;
2220 }
2221
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002222 return -1;
2223}
2224
Jim Grosbach3d1eac82011-08-26 21:43:41 +00002225/// parseITCondCode - Try to parse a condition code for an IT instruction.
2226ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2227parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2228 SMLoc S = Parser.getTok().getLoc();
2229 const AsmToken &Tok = Parser.getTok();
2230 if (!Tok.is(AsmToken::Identifier))
2231 return MatchOperand_NoMatch;
2232 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2233 .Case("eq", ARMCC::EQ)
2234 .Case("ne", ARMCC::NE)
2235 .Case("hs", ARMCC::HS)
2236 .Case("cs", ARMCC::HS)
2237 .Case("lo", ARMCC::LO)
2238 .Case("cc", ARMCC::LO)
2239 .Case("mi", ARMCC::MI)
2240 .Case("pl", ARMCC::PL)
2241 .Case("vs", ARMCC::VS)
2242 .Case("vc", ARMCC::VC)
2243 .Case("hi", ARMCC::HI)
2244 .Case("ls", ARMCC::LS)
2245 .Case("ge", ARMCC::GE)
2246 .Case("lt", ARMCC::LT)
2247 .Case("gt", ARMCC::GT)
2248 .Case("le", ARMCC::LE)
2249 .Case("al", ARMCC::AL)
2250 .Default(~0U);
2251 if (CC == ~0U)
2252 return MatchOperand_NoMatch;
2253 Parser.Lex(); // Eat the token.
2254
2255 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2256
2257 return MatchOperand_Success;
2258}
2259
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002260/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002261/// token must be an Identifier when called, and if it is a coprocessor
2262/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002263ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002264parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002265 SMLoc S = Parser.getTok().getLoc();
2266 const AsmToken &Tok = Parser.getTok();
Jim Grosbach54a20ed2011-10-12 20:54:17 +00002267 if (Tok.isNot(AsmToken::Identifier))
2268 return MatchOperand_NoMatch;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002269
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002270 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002271 if (Num == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002272 return MatchOperand_NoMatch;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002273
2274 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002275 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002276 return MatchOperand_Success;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002277}
2278
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002279/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002280/// token must be an Identifier when called, and if it is a coprocessor
2281/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002282ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002283parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002284 SMLoc S = Parser.getTok().getLoc();
2285 const AsmToken &Tok = Parser.getTok();
Jim Grosbach54a20ed2011-10-12 20:54:17 +00002286 if (Tok.isNot(AsmToken::Identifier))
2287 return MatchOperand_NoMatch;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002288
2289 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2290 if (Reg == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002291 return MatchOperand_NoMatch;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002292
2293 Parser.Lex(); // Eat identifier token.
2294 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002295 return MatchOperand_Success;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002296}
2297
Jim Grosbach48399582011-10-12 17:34:41 +00002298/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2299/// coproc_option : '{' imm0_255 '}'
2300ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2301parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2302 SMLoc S = Parser.getTok().getLoc();
2303
2304 // If this isn't a '{', this isn't a coprocessor immediate operand.
2305 if (Parser.getTok().isNot(AsmToken::LCurly))
2306 return MatchOperand_NoMatch;
2307 Parser.Lex(); // Eat the '{'
2308
2309 const MCExpr *Expr;
2310 SMLoc Loc = Parser.getTok().getLoc();
2311 if (getParser().ParseExpression(Expr)) {
2312 Error(Loc, "illegal expression");
2313 return MatchOperand_ParseFail;
2314 }
2315 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2316 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2317 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2318 return MatchOperand_ParseFail;
2319 }
2320 int Val = CE->getValue();
2321
2322 // Check for and consume the closing '}'
2323 if (Parser.getTok().isNot(AsmToken::RCurly))
2324 return MatchOperand_ParseFail;
2325 SMLoc E = Parser.getTok().getLoc();
2326 Parser.Lex(); // Eat the '}'
2327
2328 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2329 return MatchOperand_Success;
2330}
2331
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002332// For register list parsing, we need to map from raw GPR register numbering
2333// to the enumeration values. The enumeration values aren't sorted by
2334// register number due to our using "sp", "lr" and "pc" as canonical names.
2335static unsigned getNextRegister(unsigned Reg) {
2336 // If this is a GPR, we need to do it manually, otherwise we can rely
2337 // on the sort ordering of the enumeration since the other reg-classes
2338 // are sane.
2339 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2340 return Reg + 1;
2341 switch(Reg) {
2342 default: assert(0 && "Invalid GPR number!");
2343 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2344 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2345 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2346 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2347 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2348 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2349 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2350 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2351 }
2352}
2353
Jim Grosbach85a23432011-11-11 21:27:40 +00002354// Return the low-subreg of a given Q register.
2355static unsigned getDRegFromQReg(unsigned QReg) {
2356 switch (QReg) {
2357 default: llvm_unreachable("expected a Q register!");
2358 case ARM::Q0: return ARM::D0;
2359 case ARM::Q1: return ARM::D2;
2360 case ARM::Q2: return ARM::D4;
2361 case ARM::Q3: return ARM::D6;
2362 case ARM::Q4: return ARM::D8;
2363 case ARM::Q5: return ARM::D10;
2364 case ARM::Q6: return ARM::D12;
2365 case ARM::Q7: return ARM::D14;
2366 case ARM::Q8: return ARM::D16;
Jim Grosbacha92a5d82011-11-15 21:01:30 +00002367 case ARM::Q9: return ARM::D18;
Jim Grosbach85a23432011-11-11 21:27:40 +00002368 case ARM::Q10: return ARM::D20;
2369 case ARM::Q11: return ARM::D22;
2370 case ARM::Q12: return ARM::D24;
2371 case ARM::Q13: return ARM::D26;
2372 case ARM::Q14: return ARM::D28;
2373 case ARM::Q15: return ARM::D30;
2374 }
2375}
2376
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002377/// Parse a register list.
Bill Wendling2063b842010-11-18 23:43:05 +00002378bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002379parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan936b0d32010-01-19 21:44:56 +00002380 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00002381 "Token is not a Left Curly Brace");
Bill Wendlinge18980a2010-11-06 22:36:58 +00002382 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002383 Parser.Lex(); // Eat '{' token.
2384 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbya2b99102009-10-09 21:12:28 +00002385
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002386 // Check the first register in the list to see what register class
2387 // this is a list of.
2388 int Reg = tryParseRegister();
2389 if (Reg == -1)
2390 return Error(RegLoc, "register expected");
2391
Jim Grosbach85a23432011-11-11 21:27:40 +00002392 // The reglist instructions have at most 16 registers, so reserve
2393 // space for that many.
2394 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2395
2396 // Allow Q regs and just interpret them as the two D sub-registers.
2397 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2398 Reg = getDRegFromQReg(Reg);
2399 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2400 ++Reg;
2401 }
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00002402 const MCRegisterClass *RC;
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002403 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2404 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2405 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2406 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2407 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2408 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2409 else
2410 return Error(RegLoc, "invalid register in register list");
2411
Jim Grosbach85a23432011-11-11 21:27:40 +00002412 // Store the register.
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002413 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbya2b99102009-10-09 21:12:28 +00002414
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002415 // This starts immediately after the first register token in the list,
2416 // so we can see either a comma or a minus (range separator) as a legal
2417 // next token.
2418 while (Parser.getTok().is(AsmToken::Comma) ||
2419 Parser.getTok().is(AsmToken::Minus)) {
2420 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache891fe82011-11-15 23:19:15 +00002421 Parser.Lex(); // Eat the minus.
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002422 SMLoc EndLoc = Parser.getTok().getLoc();
2423 int EndReg = tryParseRegister();
2424 if (EndReg == -1)
2425 return Error(EndLoc, "register expected");
Jim Grosbach85a23432011-11-11 21:27:40 +00002426 // Allow Q regs and just interpret them as the two D sub-registers.
2427 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2428 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002429 // If the register is the same as the start reg, there's nothing
2430 // more to do.
2431 if (Reg == EndReg)
2432 continue;
2433 // The register must be in the same register class as the first.
2434 if (!RC->contains(EndReg))
2435 return Error(EndLoc, "invalid register in register list");
2436 // Ranges must go from low to high.
2437 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2438 return Error(EndLoc, "bad range in register list");
Kevin Enderbya2b99102009-10-09 21:12:28 +00002439
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002440 // Add all the registers in the range to the register list.
2441 while (Reg != EndReg) {
2442 Reg = getNextRegister(Reg);
2443 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2444 }
2445 continue;
2446 }
2447 Parser.Lex(); // Eat the comma.
2448 RegLoc = Parser.getTok().getLoc();
2449 int OldReg = Reg;
2450 Reg = tryParseRegister();
2451 if (Reg == -1)
Jim Grosbach3337e392011-09-12 23:36:42 +00002452 return Error(RegLoc, "register expected");
Jim Grosbach85a23432011-11-11 21:27:40 +00002453 // Allow Q regs and just interpret them as the two D sub-registers.
2454 bool isQReg = false;
2455 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2456 Reg = getDRegFromQReg(Reg);
2457 isQReg = true;
2458 }
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002459 // The register must be in the same register class as the first.
2460 if (!RC->contains(Reg))
2461 return Error(RegLoc, "invalid register in register list");
2462 // List must be monotonically increasing.
2463 if (getARMRegisterNumbering(Reg) <= getARMRegisterNumbering(OldReg))
2464 return Error(RegLoc, "register list not in ascending order");
2465 // VFP register lists must also be contiguous.
2466 // It's OK to use the enumeration values directly here rather, as the
2467 // VFP register classes have the enum sorted properly.
2468 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2469 Reg != OldReg + 1)
2470 return Error(RegLoc, "non-contiguous register range");
2471 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbach85a23432011-11-11 21:27:40 +00002472 if (isQReg)
2473 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge18980a2010-11-06 22:36:58 +00002474 }
2475
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002476 SMLoc E = Parser.getTok().getLoc();
2477 if (Parser.getTok().isNot(AsmToken::RCurly))
2478 return Error(E, "'}' expected");
2479 Parser.Lex(); // Eat '}' token.
2480
Bill Wendling2063b842010-11-18 23:43:05 +00002481 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2482 return false;
Kevin Enderbya2b99102009-10-09 21:12:28 +00002483}
2484
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002485// Helper function to parse the lane index for vector lists.
2486ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2487parseVectorLane(VectorLaneTy &LaneKind) {
2488 if (Parser.getTok().is(AsmToken::LBrac)) {
2489 Parser.Lex(); // Eat the '['.
2490 if (Parser.getTok().is(AsmToken::RBrac)) {
2491 // "Dn[]" is the 'all lanes' syntax.
2492 LaneKind = AllLanes;
2493 Parser.Lex(); // Eat the ']'.
2494 return MatchOperand_Success;
2495 }
2496 // FIXME: Other lane kinds as we add them.
2497 Error(Parser.getTok().getLoc(), "FIXME: Unexpected lane kind.");
2498 return MatchOperand_ParseFail;
2499 }
2500 LaneKind = NoLanes;
2501 return MatchOperand_Success;
2502}
2503
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002504// parse a vector register list
2505ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2506parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002507 VectorLaneTy LaneKind;
Jim Grosbach8d579232011-11-15 21:45:55 +00002508 SMLoc S = Parser.getTok().getLoc();
2509 // As an extension (to match gas), support a plain D register or Q register
2510 // (without encosing curly braces) as a single or double entry list,
2511 // respectively.
2512 if (Parser.getTok().is(AsmToken::Identifier)) {
2513 int Reg = tryParseRegister();
2514 if (Reg == -1)
2515 return MatchOperand_NoMatch;
2516 SMLoc E = Parser.getTok().getLoc();
2517 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002518 OperandMatchResultTy Res = parseVectorLane(LaneKind);
2519 if (Res != MatchOperand_Success)
2520 return Res;
2521 switch (LaneKind) {
2522 default:
2523 assert(0 && "unexpected lane kind!");
2524 case NoLanes:
2525 E = Parser.getTok().getLoc();
2526 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, S, E));
2527 break;
2528 case AllLanes:
2529 E = Parser.getTok().getLoc();
2530 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, S, E));
2531 break;
2532 }
Jim Grosbach8d579232011-11-15 21:45:55 +00002533 return MatchOperand_Success;
2534 }
2535 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2536 Reg = getDRegFromQReg(Reg);
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002537 OperandMatchResultTy Res = parseVectorLane(LaneKind);
2538 if (Res != MatchOperand_Success)
2539 return Res;
2540 switch (LaneKind) {
2541 default:
2542 assert(0 && "unexpected lane kind!");
2543 case NoLanes:
2544 E = Parser.getTok().getLoc();
2545 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, S, E));
2546 break;
2547 case AllLanes:
2548 E = Parser.getTok().getLoc();
2549 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, S, E));
2550 break;
2551 }
Jim Grosbach8d579232011-11-15 21:45:55 +00002552 return MatchOperand_Success;
2553 }
2554 Error(S, "vector register expected");
2555 return MatchOperand_ParseFail;
2556 }
2557
2558 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002559 return MatchOperand_NoMatch;
2560
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002561 Parser.Lex(); // Eat '{' token.
2562 SMLoc RegLoc = Parser.getTok().getLoc();
2563
2564 int Reg = tryParseRegister();
2565 if (Reg == -1) {
2566 Error(RegLoc, "register expected");
2567 return MatchOperand_ParseFail;
2568 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002569 unsigned Count = 1;
Jim Grosbach080a4992011-10-28 00:06:50 +00002570 unsigned FirstReg = Reg;
2571 // The list is of D registers, but we also allow Q regs and just interpret
2572 // them as the two D sub-registers.
2573 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2574 FirstReg = Reg = getDRegFromQReg(Reg);
2575 ++Reg;
2576 ++Count;
2577 }
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002578 if (parseVectorLane(LaneKind) != MatchOperand_Success)
2579 return MatchOperand_ParseFail;
Jim Grosbach080a4992011-10-28 00:06:50 +00002580
Jim Grosbache891fe82011-11-15 23:19:15 +00002581 while (Parser.getTok().is(AsmToken::Comma) ||
2582 Parser.getTok().is(AsmToken::Minus)) {
2583 if (Parser.getTok().is(AsmToken::Minus)) {
2584 Parser.Lex(); // Eat the minus.
2585 SMLoc EndLoc = Parser.getTok().getLoc();
2586 int EndReg = tryParseRegister();
2587 if (EndReg == -1) {
2588 Error(EndLoc, "register expected");
2589 return MatchOperand_ParseFail;
2590 }
2591 // Allow Q regs and just interpret them as the two D sub-registers.
2592 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2593 EndReg = getDRegFromQReg(EndReg) + 1;
2594 // If the register is the same as the start reg, there's nothing
2595 // more to do.
2596 if (Reg == EndReg)
2597 continue;
2598 // The register must be in the same register class as the first.
2599 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
2600 Error(EndLoc, "invalid register in register list");
2601 return MatchOperand_ParseFail;
2602 }
2603 // Ranges must go from low to high.
2604 if (Reg > EndReg) {
2605 Error(EndLoc, "bad range in register list");
2606 return MatchOperand_ParseFail;
2607 }
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002608 // Parse the lane specifier if present.
2609 VectorLaneTy NextLaneKind;
2610 if (parseVectorLane(NextLaneKind) != MatchOperand_Success)
2611 return MatchOperand_ParseFail;
2612 if (NextLaneKind != LaneKind) {
2613 Error(EndLoc, "mismatched lane index in register list");
2614 return MatchOperand_ParseFail;
2615 }
2616 EndLoc = Parser.getTok().getLoc();
Jim Grosbache891fe82011-11-15 23:19:15 +00002617
2618 // Add all the registers in the range to the register list.
2619 Count += EndReg - Reg;
2620 Reg = EndReg;
2621 continue;
2622 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002623 Parser.Lex(); // Eat the comma.
2624 RegLoc = Parser.getTok().getLoc();
2625 int OldReg = Reg;
2626 Reg = tryParseRegister();
2627 if (Reg == -1) {
2628 Error(RegLoc, "register expected");
2629 return MatchOperand_ParseFail;
2630 }
Jim Grosbach080a4992011-10-28 00:06:50 +00002631 // vector register lists must be contiguous.
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002632 // It's OK to use the enumeration values directly here rather, as the
2633 // VFP register classes have the enum sorted properly.
Jim Grosbach080a4992011-10-28 00:06:50 +00002634 //
2635 // The list is of D registers, but we also allow Q regs and just interpret
2636 // them as the two D sub-registers.
2637 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2638 Reg = getDRegFromQReg(Reg);
2639 if (Reg != OldReg + 1) {
2640 Error(RegLoc, "non-contiguous register range");
2641 return MatchOperand_ParseFail;
2642 }
2643 ++Reg;
2644 Count += 2;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002645 // Parse the lane specifier if present.
2646 VectorLaneTy NextLaneKind;
2647 SMLoc EndLoc = Parser.getTok().getLoc();
2648 if (parseVectorLane(NextLaneKind) != MatchOperand_Success)
2649 return MatchOperand_ParseFail;
2650 if (NextLaneKind != LaneKind) {
2651 Error(EndLoc, "mismatched lane index in register list");
2652 return MatchOperand_ParseFail;
2653 }
Jim Grosbach080a4992011-10-28 00:06:50 +00002654 continue;
2655 }
2656 // Normal D register. Just check that it's contiguous and keep going.
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002657 if (Reg != OldReg + 1) {
2658 Error(RegLoc, "non-contiguous register range");
2659 return MatchOperand_ParseFail;
2660 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002661 ++Count;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002662 // Parse the lane specifier if present.
2663 VectorLaneTy NextLaneKind;
2664 SMLoc EndLoc = Parser.getTok().getLoc();
2665 if (parseVectorLane(NextLaneKind) != MatchOperand_Success)
2666 return MatchOperand_ParseFail;
2667 if (NextLaneKind != LaneKind) {
2668 Error(EndLoc, "mismatched lane index in register list");
2669 return MatchOperand_ParseFail;
2670 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002671 }
2672
2673 SMLoc E = Parser.getTok().getLoc();
2674 if (Parser.getTok().isNot(AsmToken::RCurly)) {
2675 Error(E, "'}' expected");
2676 return MatchOperand_ParseFail;
2677 }
2678 Parser.Lex(); // Eat '}' token.
2679
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002680 switch (LaneKind) {
2681 default:
2682 assert(0 && "unexpected lane kind in register list.");
2683 case NoLanes:
2684 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count, S, E));
2685 break;
2686 case AllLanes:
2687 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
2688 S, E));
2689 break;
2690 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002691 return MatchOperand_Success;
2692}
2693
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002694/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002695ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002696parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002697 SMLoc S = Parser.getTok().getLoc();
2698 const AsmToken &Tok = Parser.getTok();
2699 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2700 StringRef OptStr = Tok.getString();
2701
2702 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2703 .Case("sy", ARM_MB::SY)
2704 .Case("st", ARM_MB::ST)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002705 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002706 .Case("ish", ARM_MB::ISH)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002707 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002708 .Case("ishst", ARM_MB::ISHST)
2709 .Case("nsh", ARM_MB::NSH)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002710 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002711 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002712 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002713 .Case("osh", ARM_MB::OSH)
2714 .Case("oshst", ARM_MB::OSHST)
2715 .Default(~0U);
2716
2717 if (Opt == ~0U)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002718 return MatchOperand_NoMatch;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002719
2720 Parser.Lex(); // Eat identifier token.
2721 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002722 return MatchOperand_Success;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002723}
2724
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002725/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002726ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002727parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002728 SMLoc S = Parser.getTok().getLoc();
2729 const AsmToken &Tok = Parser.getTok();
2730 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2731 StringRef IFlagsStr = Tok.getString();
2732
Owen Anderson10c5b122011-10-05 17:16:40 +00002733 // An iflags string of "none" is interpreted to mean that none of the AIF
2734 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002735 unsigned IFlags = 0;
Owen Anderson10c5b122011-10-05 17:16:40 +00002736 if (IFlagsStr != "none") {
2737 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2738 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2739 .Case("a", ARM_PROC::A)
2740 .Case("i", ARM_PROC::I)
2741 .Case("f", ARM_PROC::F)
2742 .Default(~0U);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002743
Owen Anderson10c5b122011-10-05 17:16:40 +00002744 // If some specific iflag is already set, it means that some letter is
2745 // present more than once, this is not acceptable.
2746 if (Flag == ~0U || (IFlags & Flag))
2747 return MatchOperand_NoMatch;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002748
Owen Anderson10c5b122011-10-05 17:16:40 +00002749 IFlags |= Flag;
2750 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002751 }
2752
2753 Parser.Lex(); // Eat identifier token.
2754 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2755 return MatchOperand_Success;
2756}
2757
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002758/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002759ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002760parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002761 SMLoc S = Parser.getTok().getLoc();
2762 const AsmToken &Tok = Parser.getTok();
2763 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2764 StringRef Mask = Tok.getString();
2765
James Molloy21efa7d2011-09-28 14:21:38 +00002766 if (isMClass()) {
2767 // See ARMv6-M 10.1.1
2768 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2769 .Case("apsr", 0)
2770 .Case("iapsr", 1)
2771 .Case("eapsr", 2)
2772 .Case("xpsr", 3)
2773 .Case("ipsr", 5)
2774 .Case("epsr", 6)
2775 .Case("iepsr", 7)
2776 .Case("msp", 8)
2777 .Case("psp", 9)
2778 .Case("primask", 16)
2779 .Case("basepri", 17)
2780 .Case("basepri_max", 18)
2781 .Case("faultmask", 19)
2782 .Case("control", 20)
2783 .Default(~0U);
2784
2785 if (FlagsVal == ~0U)
2786 return MatchOperand_NoMatch;
2787
2788 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
2789 // basepri, basepri_max and faultmask only valid for V7m.
2790 return MatchOperand_NoMatch;
2791
2792 Parser.Lex(); // Eat identifier token.
2793 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2794 return MatchOperand_Success;
2795 }
2796
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002797 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
2798 size_t Start = 0, Next = Mask.find('_');
2799 StringRef Flags = "";
Benjamin Kramer20baffb2011-11-06 20:37:06 +00002800 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002801 if (Next != StringRef::npos)
2802 Flags = Mask.slice(Next+1, Mask.size());
2803
2804 // FlagsVal contains the complete mask:
2805 // 3-0: Mask
2806 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2807 unsigned FlagsVal = 0;
2808
2809 if (SpecReg == "apsr") {
2810 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachd25c2cd2011-07-19 22:45:10 +00002811 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002812 .Case("g", 0x4) // same as CPSR_s
2813 .Case("nzcvqg", 0xc) // same as CPSR_fs
2814 .Default(~0U);
2815
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00002816 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002817 if (!Flags.empty())
2818 return MatchOperand_NoMatch;
2819 else
Jim Grosbach0ecd3952011-09-14 20:03:46 +00002820 FlagsVal = 8; // No flag
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00002821 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002822 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes54452132011-05-25 00:35:03 +00002823 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
2824 Flags = "fc";
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002825 for (int i = 0, e = Flags.size(); i != e; ++i) {
2826 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
2827 .Case("c", 1)
2828 .Case("x", 2)
2829 .Case("s", 4)
2830 .Case("f", 8)
2831 .Default(~0U);
2832
2833 // If some specific flag is already set, it means that some letter is
2834 // present more than once, this is not acceptable.
2835 if (FlagsVal == ~0U || (FlagsVal & Flag))
2836 return MatchOperand_NoMatch;
2837 FlagsVal |= Flag;
2838 }
2839 } else // No match for special register.
2840 return MatchOperand_NoMatch;
2841
Owen Anderson03a173e2011-10-21 18:43:28 +00002842 // Special register without flags is NOT equivalent to "fc" flags.
2843 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
2844 // two lines would enable gas compatibility at the expense of breaking
2845 // round-tripping.
2846 //
2847 // if (!FlagsVal)
2848 // FlagsVal = 0x9;
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002849
2850 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2851 if (SpecReg == "spsr")
2852 FlagsVal |= 16;
2853
2854 Parser.Lex(); // Eat identifier token.
2855 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2856 return MatchOperand_Success;
2857}
2858
Jim Grosbach27c1e252011-07-21 17:23:04 +00002859ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2860parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
2861 int Low, int High) {
2862 const AsmToken &Tok = Parser.getTok();
2863 if (Tok.isNot(AsmToken::Identifier)) {
2864 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2865 return MatchOperand_ParseFail;
2866 }
2867 StringRef ShiftName = Tok.getString();
Benjamin Kramer20baffb2011-11-06 20:37:06 +00002868 std::string LowerOp = Op.lower();
2869 std::string UpperOp = Op.upper();
Jim Grosbach27c1e252011-07-21 17:23:04 +00002870 if (ShiftName != LowerOp && ShiftName != UpperOp) {
2871 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2872 return MatchOperand_ParseFail;
2873 }
2874 Parser.Lex(); // Eat shift type token.
2875
2876 // There must be a '#' and a shift amount.
2877 if (Parser.getTok().isNot(AsmToken::Hash)) {
2878 Error(Parser.getTok().getLoc(), "'#' expected");
2879 return MatchOperand_ParseFail;
2880 }
2881 Parser.Lex(); // Eat hash token.
2882
2883 const MCExpr *ShiftAmount;
2884 SMLoc Loc = Parser.getTok().getLoc();
2885 if (getParser().ParseExpression(ShiftAmount)) {
2886 Error(Loc, "illegal expression");
2887 return MatchOperand_ParseFail;
2888 }
2889 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2890 if (!CE) {
2891 Error(Loc, "constant expression expected");
2892 return MatchOperand_ParseFail;
2893 }
2894 int Val = CE->getValue();
2895 if (Val < Low || Val > High) {
2896 Error(Loc, "immediate value out of range");
2897 return MatchOperand_ParseFail;
2898 }
2899
2900 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
2901
2902 return MatchOperand_Success;
2903}
2904
Jim Grosbach0a547702011-07-22 17:44:50 +00002905ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2906parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2907 const AsmToken &Tok = Parser.getTok();
2908 SMLoc S = Tok.getLoc();
2909 if (Tok.isNot(AsmToken::Identifier)) {
2910 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2911 return MatchOperand_ParseFail;
2912 }
2913 int Val = StringSwitch<int>(Tok.getString())
2914 .Case("be", 1)
2915 .Case("le", 0)
2916 .Default(-1);
2917 Parser.Lex(); // Eat the token.
2918
2919 if (Val == -1) {
2920 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2921 return MatchOperand_ParseFail;
2922 }
2923 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
2924 getContext()),
2925 S, Parser.getTok().getLoc()));
2926 return MatchOperand_Success;
2927}
2928
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002929/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
2930/// instructions. Legal values are:
2931/// lsl #n 'n' in [0,31]
2932/// asr #n 'n' in [1,32]
2933/// n == 32 encoded as n == 0.
2934ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2935parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2936 const AsmToken &Tok = Parser.getTok();
2937 SMLoc S = Tok.getLoc();
2938 if (Tok.isNot(AsmToken::Identifier)) {
2939 Error(S, "shift operator 'asr' or 'lsl' expected");
2940 return MatchOperand_ParseFail;
2941 }
2942 StringRef ShiftName = Tok.getString();
2943 bool isASR;
2944 if (ShiftName == "lsl" || ShiftName == "LSL")
2945 isASR = false;
2946 else if (ShiftName == "asr" || ShiftName == "ASR")
2947 isASR = true;
2948 else {
2949 Error(S, "shift operator 'asr' or 'lsl' expected");
2950 return MatchOperand_ParseFail;
2951 }
2952 Parser.Lex(); // Eat the operator.
2953
2954 // A '#' and a shift amount.
2955 if (Parser.getTok().isNot(AsmToken::Hash)) {
2956 Error(Parser.getTok().getLoc(), "'#' expected");
2957 return MatchOperand_ParseFail;
2958 }
2959 Parser.Lex(); // Eat hash token.
2960
2961 const MCExpr *ShiftAmount;
2962 SMLoc E = Parser.getTok().getLoc();
2963 if (getParser().ParseExpression(ShiftAmount)) {
2964 Error(E, "malformed shift expression");
2965 return MatchOperand_ParseFail;
2966 }
2967 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2968 if (!CE) {
2969 Error(E, "shift amount must be an immediate");
2970 return MatchOperand_ParseFail;
2971 }
2972
2973 int64_t Val = CE->getValue();
2974 if (isASR) {
2975 // Shift amount must be in [1,32]
2976 if (Val < 1 || Val > 32) {
2977 Error(E, "'asr' shift amount must be in range [1,32]");
2978 return MatchOperand_ParseFail;
2979 }
Owen Andersonf01e2de2011-09-26 21:06:22 +00002980 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
2981 if (isThumb() && Val == 32) {
2982 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
2983 return MatchOperand_ParseFail;
2984 }
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002985 if (Val == 32) Val = 0;
2986 } else {
2987 // Shift amount must be in [1,32]
2988 if (Val < 0 || Val > 31) {
2989 Error(E, "'lsr' shift amount must be in range [0,31]");
2990 return MatchOperand_ParseFail;
2991 }
2992 }
2993
2994 E = Parser.getTok().getLoc();
2995 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
2996
2997 return MatchOperand_Success;
2998}
2999
Jim Grosbach833b9d32011-07-27 20:15:40 +00003000/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3001/// of instructions. Legal values are:
3002/// ror #n 'n' in {0, 8, 16, 24}
3003ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3004parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3005 const AsmToken &Tok = Parser.getTok();
3006 SMLoc S = Tok.getLoc();
Jim Grosbach82213192011-09-19 20:29:33 +00003007 if (Tok.isNot(AsmToken::Identifier))
3008 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00003009 StringRef ShiftName = Tok.getString();
Jim Grosbach82213192011-09-19 20:29:33 +00003010 if (ShiftName != "ror" && ShiftName != "ROR")
3011 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00003012 Parser.Lex(); // Eat the operator.
3013
3014 // A '#' and a rotate amount.
3015 if (Parser.getTok().isNot(AsmToken::Hash)) {
3016 Error(Parser.getTok().getLoc(), "'#' expected");
3017 return MatchOperand_ParseFail;
3018 }
3019 Parser.Lex(); // Eat hash token.
3020
3021 const MCExpr *ShiftAmount;
3022 SMLoc E = Parser.getTok().getLoc();
3023 if (getParser().ParseExpression(ShiftAmount)) {
3024 Error(E, "malformed rotate expression");
3025 return MatchOperand_ParseFail;
3026 }
3027 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3028 if (!CE) {
3029 Error(E, "rotate amount must be an immediate");
3030 return MatchOperand_ParseFail;
3031 }
3032
3033 int64_t Val = CE->getValue();
3034 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3035 // normally, zero is represented in asm by omitting the rotate operand
3036 // entirely.
3037 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3038 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3039 return MatchOperand_ParseFail;
3040 }
3041
3042 E = Parser.getTok().getLoc();
3043 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3044
3045 return MatchOperand_Success;
3046}
3047
Jim Grosbach864b6092011-07-28 21:34:26 +00003048ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3049parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3050 SMLoc S = Parser.getTok().getLoc();
3051 // The bitfield descriptor is really two operands, the LSB and the width.
3052 if (Parser.getTok().isNot(AsmToken::Hash)) {
3053 Error(Parser.getTok().getLoc(), "'#' expected");
3054 return MatchOperand_ParseFail;
3055 }
3056 Parser.Lex(); // Eat hash token.
3057
3058 const MCExpr *LSBExpr;
3059 SMLoc E = Parser.getTok().getLoc();
3060 if (getParser().ParseExpression(LSBExpr)) {
3061 Error(E, "malformed immediate expression");
3062 return MatchOperand_ParseFail;
3063 }
3064 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3065 if (!CE) {
3066 Error(E, "'lsb' operand must be an immediate");
3067 return MatchOperand_ParseFail;
3068 }
3069
3070 int64_t LSB = CE->getValue();
3071 // The LSB must be in the range [0,31]
3072 if (LSB < 0 || LSB > 31) {
3073 Error(E, "'lsb' operand must be in the range [0,31]");
3074 return MatchOperand_ParseFail;
3075 }
3076 E = Parser.getTok().getLoc();
3077
3078 // Expect another immediate operand.
3079 if (Parser.getTok().isNot(AsmToken::Comma)) {
3080 Error(Parser.getTok().getLoc(), "too few operands");
3081 return MatchOperand_ParseFail;
3082 }
3083 Parser.Lex(); // Eat hash token.
3084 if (Parser.getTok().isNot(AsmToken::Hash)) {
3085 Error(Parser.getTok().getLoc(), "'#' expected");
3086 return MatchOperand_ParseFail;
3087 }
3088 Parser.Lex(); // Eat hash token.
3089
3090 const MCExpr *WidthExpr;
3091 if (getParser().ParseExpression(WidthExpr)) {
3092 Error(E, "malformed immediate expression");
3093 return MatchOperand_ParseFail;
3094 }
3095 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3096 if (!CE) {
3097 Error(E, "'width' operand must be an immediate");
3098 return MatchOperand_ParseFail;
3099 }
3100
3101 int64_t Width = CE->getValue();
3102 // The LSB must be in the range [1,32-lsb]
3103 if (Width < 1 || Width > 32 - LSB) {
3104 Error(E, "'width' operand must be in the range [1,32-lsb]");
3105 return MatchOperand_ParseFail;
3106 }
3107 E = Parser.getTok().getLoc();
3108
3109 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3110
3111 return MatchOperand_Success;
3112}
3113
Jim Grosbachd3595712011-08-03 23:50:40 +00003114ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3115parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3116 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachc320c852011-08-05 21:28:30 +00003117 // postidx_reg := '+' register {, shift}
3118 // | '-' register {, shift}
3119 // | register {, shift}
Jim Grosbachd3595712011-08-03 23:50:40 +00003120
3121 // This method must return MatchOperand_NoMatch without consuming any tokens
3122 // in the case where there is no match, as other alternatives take other
3123 // parse methods.
3124 AsmToken Tok = Parser.getTok();
3125 SMLoc S = Tok.getLoc();
3126 bool haveEaten = false;
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00003127 bool isAdd = true;
Jim Grosbachd3595712011-08-03 23:50:40 +00003128 int Reg = -1;
3129 if (Tok.is(AsmToken::Plus)) {
3130 Parser.Lex(); // Eat the '+' token.
3131 haveEaten = true;
3132 } else if (Tok.is(AsmToken::Minus)) {
3133 Parser.Lex(); // Eat the '-' token.
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00003134 isAdd = false;
Jim Grosbachd3595712011-08-03 23:50:40 +00003135 haveEaten = true;
3136 }
3137 if (Parser.getTok().is(AsmToken::Identifier))
3138 Reg = tryParseRegister();
3139 if (Reg == -1) {
3140 if (!haveEaten)
3141 return MatchOperand_NoMatch;
3142 Error(Parser.getTok().getLoc(), "register expected");
3143 return MatchOperand_ParseFail;
3144 }
3145 SMLoc E = Parser.getTok().getLoc();
3146
Jim Grosbachc320c852011-08-05 21:28:30 +00003147 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3148 unsigned ShiftImm = 0;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00003149 if (Parser.getTok().is(AsmToken::Comma)) {
3150 Parser.Lex(); // Eat the ','.
3151 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3152 return MatchOperand_ParseFail;
3153 }
Jim Grosbachc320c852011-08-05 21:28:30 +00003154
3155 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3156 ShiftImm, S, E));
Jim Grosbachd3595712011-08-03 23:50:40 +00003157
3158 return MatchOperand_Success;
3159}
3160
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00003161ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3162parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3163 // Check for a post-index addressing register operand. Specifically:
3164 // am3offset := '+' register
3165 // | '-' register
3166 // | register
3167 // | # imm
3168 // | # + imm
3169 // | # - imm
3170
3171 // This method must return MatchOperand_NoMatch without consuming any tokens
3172 // in the case where there is no match, as other alternatives take other
3173 // parse methods.
3174 AsmToken Tok = Parser.getTok();
3175 SMLoc S = Tok.getLoc();
3176
3177 // Do immediates first, as we always parse those if we have a '#'.
3178 if (Parser.getTok().is(AsmToken::Hash)) {
3179 Parser.Lex(); // Eat the '#'.
3180 // Explicitly look for a '-', as we need to encode negative zero
3181 // differently.
3182 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3183 const MCExpr *Offset;
3184 if (getParser().ParseExpression(Offset))
3185 return MatchOperand_ParseFail;
3186 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3187 if (!CE) {
3188 Error(S, "constant expression expected");
3189 return MatchOperand_ParseFail;
3190 }
3191 SMLoc E = Tok.getLoc();
3192 // Negative zero is encoded as the flag value INT32_MIN.
3193 int32_t Val = CE->getValue();
3194 if (isNegative && Val == 0)
3195 Val = INT32_MIN;
3196
3197 Operands.push_back(
3198 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3199
3200 return MatchOperand_Success;
3201 }
3202
3203
3204 bool haveEaten = false;
3205 bool isAdd = true;
3206 int Reg = -1;
3207 if (Tok.is(AsmToken::Plus)) {
3208 Parser.Lex(); // Eat the '+' token.
3209 haveEaten = true;
3210 } else if (Tok.is(AsmToken::Minus)) {
3211 Parser.Lex(); // Eat the '-' token.
3212 isAdd = false;
3213 haveEaten = true;
3214 }
3215 if (Parser.getTok().is(AsmToken::Identifier))
3216 Reg = tryParseRegister();
3217 if (Reg == -1) {
3218 if (!haveEaten)
3219 return MatchOperand_NoMatch;
3220 Error(Parser.getTok().getLoc(), "register expected");
3221 return MatchOperand_ParseFail;
3222 }
3223 SMLoc E = Parser.getTok().getLoc();
3224
3225 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3226 0, S, E));
3227
3228 return MatchOperand_Success;
3229}
3230
Jim Grosbach7db8d692011-09-08 22:07:06 +00003231/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3232/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3233/// when they refer multiple MIOperands inside a single one.
3234bool ARMAsmParser::
3235cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3236 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3237 // Rt, Rt2
3238 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3239 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3240 // Create a writeback register dummy placeholder.
3241 Inst.addOperand(MCOperand::CreateReg(0));
3242 // addr
3243 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3244 // pred
3245 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3246 return true;
3247}
3248
3249/// cvtT2StrdPre - Convert parsed operands to MCInst.
3250/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3251/// when they refer multiple MIOperands inside a single one.
3252bool ARMAsmParser::
3253cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3254 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3255 // Create a writeback register dummy placeholder.
3256 Inst.addOperand(MCOperand::CreateReg(0));
3257 // Rt, Rt2
3258 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3259 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3260 // addr
3261 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3262 // pred
3263 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3264 return true;
3265}
3266
Jim Grosbachc086f682011-09-08 00:39:19 +00003267/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3268/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3269/// when they refer multiple MIOperands inside a single one.
3270bool ARMAsmParser::
3271cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3272 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3273 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3274
3275 // Create a writeback register dummy placeholder.
3276 Inst.addOperand(MCOperand::CreateImm(0));
3277
3278 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3279 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3280 return true;
3281}
3282
Jim Grosbach9c0b86a2011-09-16 21:55:56 +00003283/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3284/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3285/// when they refer multiple MIOperands inside a single one.
3286bool ARMAsmParser::
3287cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3288 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3289 // Create a writeback register dummy placeholder.
3290 Inst.addOperand(MCOperand::CreateImm(0));
3291 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3292 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3293 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3294 return true;
3295}
3296
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003297/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003298/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3299/// when they refer multiple MIOperands inside a single one.
3300bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003301cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003302 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3303 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3304
3305 // Create a writeback register dummy placeholder.
3306 Inst.addOperand(MCOperand::CreateImm(0));
3307
Jim Grosbachd3595712011-08-03 23:50:40 +00003308 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003309 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3310 return true;
3311}
3312
Owen Anderson16d33f32011-08-26 20:43:14 +00003313/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3314/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3315/// when they refer multiple MIOperands inside a single one.
3316bool ARMAsmParser::
3317cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3318 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3319 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3320
3321 // Create a writeback register dummy placeholder.
3322 Inst.addOperand(MCOperand::CreateImm(0));
3323
3324 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3325 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3326 return true;
3327}
3328
3329
Jim Grosbachd564bf32011-08-11 19:22:40 +00003330/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3331/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3332/// when they refer multiple MIOperands inside a single one.
3333bool ARMAsmParser::
3334cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3335 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3336 // Create a writeback register dummy placeholder.
3337 Inst.addOperand(MCOperand::CreateImm(0));
3338 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3339 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3340 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3341 return true;
3342}
3343
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003344/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003345/// 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::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003348cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003349 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3350 // Create a writeback register dummy placeholder.
3351 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd564bf32011-08-11 19:22:40 +00003352 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3353 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3354 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbachd3595712011-08-03 23:50:40 +00003355 return true;
3356}
3357
Jim Grosbachd886f8c2011-08-11 21:17:22 +00003358/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3359/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3360/// when they refer multiple MIOperands inside a single one.
3361bool ARMAsmParser::
3362cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3363 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3364 // Create a writeback register dummy placeholder.
3365 Inst.addOperand(MCOperand::CreateImm(0));
3366 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3367 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3368 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3369 return true;
3370}
3371
Jim Grosbachd3595712011-08-03 23:50:40 +00003372/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3373/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3374/// when they refer multiple MIOperands inside a single one.
3375bool ARMAsmParser::
3376cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3377 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3378 // Rt
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003379 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbachd3595712011-08-03 23:50:40 +00003380 // Create a writeback register dummy placeholder.
3381 Inst.addOperand(MCOperand::CreateImm(0));
3382 // addr
3383 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3384 // offset
3385 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3386 // pred
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003387 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3388 return true;
3389}
3390
Jim Grosbachd3595712011-08-03 23:50:40 +00003391/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003392/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3393/// when they refer multiple MIOperands inside a single one.
3394bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003395cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3396 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3397 // Rt
Owen Andersonb0e68992011-07-28 17:18:57 +00003398 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003399 // Create a writeback register dummy placeholder.
3400 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd3595712011-08-03 23:50:40 +00003401 // addr
3402 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3403 // offset
3404 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3405 // pred
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003406 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3407 return true;
3408}
3409
Jim Grosbachd3595712011-08-03 23:50:40 +00003410/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003411/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3412/// when they refer multiple MIOperands inside a single one.
3413bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003414cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3415 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003416 // Create a writeback register dummy placeholder.
3417 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd3595712011-08-03 23:50:40 +00003418 // Rt
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003419 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbachd3595712011-08-03 23:50:40 +00003420 // addr
3421 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3422 // offset
3423 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3424 // pred
3425 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3426 return true;
3427}
3428
3429/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3430/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3431/// when they refer multiple MIOperands inside a single one.
3432bool ARMAsmParser::
3433cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3434 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3435 // Create a writeback register dummy placeholder.
3436 Inst.addOperand(MCOperand::CreateImm(0));
3437 // Rt
3438 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3439 // addr
3440 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3441 // offset
3442 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3443 // pred
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003444 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3445 return true;
3446}
3447
Jim Grosbach5b96b802011-08-10 20:29:19 +00003448/// cvtLdrdPre - Convert parsed operands to MCInst.
3449/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3450/// when they refer multiple MIOperands inside a single one.
3451bool ARMAsmParser::
3452cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3453 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3454 // Rt, Rt2
3455 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3456 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3457 // Create a writeback register dummy placeholder.
3458 Inst.addOperand(MCOperand::CreateImm(0));
3459 // addr
3460 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3461 // pred
3462 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3463 return true;
3464}
3465
Jim Grosbacheb09f492011-08-11 20:28:23 +00003466/// cvtStrdPre - Convert parsed operands to MCInst.
3467/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3468/// when they refer multiple MIOperands inside a single one.
3469bool ARMAsmParser::
3470cvtStrdPre(MCInst &Inst, unsigned Opcode,
3471 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3472 // Create a writeback register dummy placeholder.
3473 Inst.addOperand(MCOperand::CreateImm(0));
3474 // Rt, Rt2
3475 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3476 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3477 // addr
3478 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3479 // pred
3480 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3481 return true;
3482}
3483
Jim Grosbachcd4dd252011-08-10 22:42:16 +00003484/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3485/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3486/// when they refer multiple MIOperands inside a single one.
3487bool ARMAsmParser::
3488cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3489 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3490 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3491 // Create a writeback register dummy placeholder.
3492 Inst.addOperand(MCOperand::CreateImm(0));
3493 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3494 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3495 return true;
3496}
3497
Jim Grosbach8e048492011-08-19 22:07:46 +00003498/// cvtThumbMultiple- Convert parsed operands to MCInst.
3499/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3500/// when they refer multiple MIOperands inside a single one.
3501bool ARMAsmParser::
3502cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3503 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3504 // The second source operand must be the same register as the destination
3505 // operand.
3506 if (Operands.size() == 6 &&
Jim Grosbach459422d2011-08-19 22:30:46 +00003507 (((ARMOperand*)Operands[3])->getReg() !=
3508 ((ARMOperand*)Operands[5])->getReg()) &&
3509 (((ARMOperand*)Operands[3])->getReg() !=
3510 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach8e048492011-08-19 22:07:46 +00003511 Error(Operands[3]->getStartLoc(),
Jim Grosbach459422d2011-08-19 22:30:46 +00003512 "destination register must match source register");
Jim Grosbach8e048492011-08-19 22:07:46 +00003513 return false;
3514 }
3515 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3516 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach5a5ce632011-11-10 22:10:12 +00003517 // If we have a three-operand form, make sure to set Rn to be the operand
3518 // that isn't the same as Rd.
3519 unsigned RegOp = 4;
3520 if (Operands.size() == 6 &&
3521 ((ARMOperand*)Operands[4])->getReg() ==
3522 ((ARMOperand*)Operands[3])->getReg())
3523 RegOp = 5;
3524 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
3525 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach8e048492011-08-19 22:07:46 +00003526 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3527
3528 return true;
3529}
Jim Grosbachcd4dd252011-08-10 22:42:16 +00003530
Jim Grosbach3ea06572011-10-24 22:16:58 +00003531bool ARMAsmParser::
3532cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3533 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3534 // Vd
Jim Grosbach182b6a02011-11-29 23:51:09 +00003535 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach3ea06572011-10-24 22:16:58 +00003536 // Create a writeback register dummy placeholder.
3537 Inst.addOperand(MCOperand::CreateImm(0));
3538 // Vn
3539 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3540 // pred
3541 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3542 return true;
3543}
3544
3545bool ARMAsmParser::
3546cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3547 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3548 // Vd
Jim Grosbach182b6a02011-11-29 23:51:09 +00003549 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach3ea06572011-10-24 22:16:58 +00003550 // Create a writeback register dummy placeholder.
3551 Inst.addOperand(MCOperand::CreateImm(0));
3552 // Vn
3553 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3554 // Vm
3555 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3556 // pred
3557 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3558 return true;
3559}
3560
Jim Grosbach05df4602011-10-31 21:50:31 +00003561bool ARMAsmParser::
3562cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
3563 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3564 // Create a writeback register dummy placeholder.
3565 Inst.addOperand(MCOperand::CreateImm(0));
3566 // Vn
3567 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3568 // Vt
Jim Grosbach182b6a02011-11-29 23:51:09 +00003569 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach05df4602011-10-31 21:50:31 +00003570 // pred
3571 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3572 return true;
3573}
3574
3575bool ARMAsmParser::
3576cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
3577 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3578 // Create a writeback register dummy placeholder.
3579 Inst.addOperand(MCOperand::CreateImm(0));
3580 // Vn
3581 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3582 // Vm
3583 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3584 // Vt
Jim Grosbach182b6a02011-11-29 23:51:09 +00003585 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach05df4602011-10-31 21:50:31 +00003586 // pred
3587 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3588 return true;
3589}
3590
Bill Wendlinge18980a2010-11-06 22:36:58 +00003591/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003592/// or an error. The first token must be a '[' when called.
Bill Wendling2063b842010-11-18 23:43:05 +00003593bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003594parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003595 SMLoc S, E;
Sean Callanan936b0d32010-01-19 21:44:56 +00003596 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00003597 "Token is not a Left Bracket");
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003598 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00003599 Parser.Lex(); // Eat left bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003600
Sean Callanan936b0d32010-01-19 21:44:56 +00003601 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003602 int BaseRegNum = tryParseRegister();
Jim Grosbachd3595712011-08-03 23:50:40 +00003603 if (BaseRegNum == -1)
3604 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003605
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00003606 // The next token must either be a comma or a closing bracket.
3607 const AsmToken &Tok = Parser.getTok();
3608 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbachd3595712011-08-03 23:50:40 +00003609 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00003610
Jim Grosbachd3595712011-08-03 23:50:40 +00003611 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003612 E = Tok.getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00003613 Parser.Lex(); // Eat right bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003614
Jim Grosbachd3595712011-08-03 23:50:40 +00003615 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbacha95ec992011-10-11 17:29:55 +00003616 0, 0, false, S, E));
Jim Grosbach32ff5582010-11-29 23:18:01 +00003617
Jim Grosbach40700e02011-09-19 18:42:21 +00003618 // If there's a pre-indexing writeback marker, '!', just add it as a token
3619 // operand. It's rather odd, but syntactically valid.
3620 if (Parser.getTok().is(AsmToken::Exclaim)) {
3621 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3622 Parser.Lex(); // Eat the '!'.
3623 }
3624
Jim Grosbachd3595712011-08-03 23:50:40 +00003625 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003626 }
Daniel Dunbarf5164f42011-01-18 05:34:24 +00003627
Jim Grosbachd3595712011-08-03 23:50:40 +00003628 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3629 Parser.Lex(); // Eat the comma.
Daniel Dunbarf5164f42011-01-18 05:34:24 +00003630
Jim Grosbacha95ec992011-10-11 17:29:55 +00003631 // If we have a ':', it's an alignment specifier.
3632 if (Parser.getTok().is(AsmToken::Colon)) {
3633 Parser.Lex(); // Eat the ':'.
3634 E = Parser.getTok().getLoc();
3635
3636 const MCExpr *Expr;
3637 if (getParser().ParseExpression(Expr))
3638 return true;
3639
3640 // The expression has to be a constant. Memory references with relocations
3641 // don't come through here, as they use the <label> forms of the relevant
3642 // instructions.
3643 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3644 if (!CE)
3645 return Error (E, "constant expression expected");
3646
3647 unsigned Align = 0;
3648 switch (CE->getValue()) {
3649 default:
3650 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3651 case 64: Align = 8; break;
3652 case 128: Align = 16; break;
3653 case 256: Align = 32; break;
3654 }
3655
3656 // Now we should have the closing ']'
3657 E = Parser.getTok().getLoc();
3658 if (Parser.getTok().isNot(AsmToken::RBrac))
3659 return Error(E, "']' expected");
3660 Parser.Lex(); // Eat right bracket token.
3661
3662 // Don't worry about range checking the value here. That's handled by
3663 // the is*() predicates.
3664 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3665 ARM_AM::no_shift, 0, Align,
3666 false, S, E));
3667
3668 // If there's a pre-indexing writeback marker, '!', just add it as a token
3669 // operand.
3670 if (Parser.getTok().is(AsmToken::Exclaim)) {
3671 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3672 Parser.Lex(); // Eat the '!'.
3673 }
3674
3675 return false;
3676 }
3677
3678 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach8279c182011-11-15 22:14:41 +00003679 // offset. Be friendly and also accept a plain integer (without a leading
3680 // hash) for gas compatibility.
3681 if (Parser.getTok().is(AsmToken::Hash) ||
3682 Parser.getTok().is(AsmToken::Integer)) {
3683 if (Parser.getTok().is(AsmToken::Hash))
3684 Parser.Lex(); // Eat the '#'.
Jim Grosbachd3595712011-08-03 23:50:40 +00003685 E = Parser.getTok().getLoc();
Daniel Dunbarf5164f42011-01-18 05:34:24 +00003686
Owen Anderson967674d2011-08-29 19:36:44 +00003687 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbachd3595712011-08-03 23:50:40 +00003688 const MCExpr *Offset;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003689 if (getParser().ParseExpression(Offset))
3690 return true;
Jim Grosbachd3595712011-08-03 23:50:40 +00003691
3692 // The expression has to be a constant. Memory references with relocations
3693 // don't come through here, as they use the <label> forms of the relevant
3694 // instructions.
3695 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3696 if (!CE)
3697 return Error (E, "constant expression expected");
3698
Owen Anderson967674d2011-08-29 19:36:44 +00003699 // If the constant was #-0, represent it as INT32_MIN.
3700 int32_t Val = CE->getValue();
3701 if (isNegative && Val == 0)
3702 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3703
Jim Grosbachd3595712011-08-03 23:50:40 +00003704 // Now we should have the closing ']'
3705 E = Parser.getTok().getLoc();
3706 if (Parser.getTok().isNot(AsmToken::RBrac))
3707 return Error(E, "']' expected");
3708 Parser.Lex(); // Eat right bracket token.
3709
3710 // Don't worry about range checking the value here. That's handled by
3711 // the is*() predicates.
3712 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbacha95ec992011-10-11 17:29:55 +00003713 ARM_AM::no_shift, 0, 0,
3714 false, S, E));
Jim Grosbachd3595712011-08-03 23:50:40 +00003715
3716 // If there's a pre-indexing writeback marker, '!', just add it as a token
3717 // operand.
3718 if (Parser.getTok().is(AsmToken::Exclaim)) {
3719 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3720 Parser.Lex(); // Eat the '!'.
3721 }
3722
3723 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003724 }
Jim Grosbachd3595712011-08-03 23:50:40 +00003725
3726 // The register offset is optionally preceded by a '+' or '-'
3727 bool isNegative = false;
3728 if (Parser.getTok().is(AsmToken::Minus)) {
3729 isNegative = true;
3730 Parser.Lex(); // Eat the '-'.
3731 } else if (Parser.getTok().is(AsmToken::Plus)) {
3732 // Nothing to do.
3733 Parser.Lex(); // Eat the '+'.
3734 }
3735
3736 E = Parser.getTok().getLoc();
3737 int OffsetRegNum = tryParseRegister();
3738 if (OffsetRegNum == -1)
3739 return Error(E, "register expected");
3740
3741 // If there's a shift operator, handle it.
3742 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00003743 unsigned ShiftImm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00003744 if (Parser.getTok().is(AsmToken::Comma)) {
3745 Parser.Lex(); // Eat the ','.
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00003746 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbachd3595712011-08-03 23:50:40 +00003747 return true;
3748 }
3749
3750 // Now we should have the closing ']'
3751 E = Parser.getTok().getLoc();
3752 if (Parser.getTok().isNot(AsmToken::RBrac))
3753 return Error(E, "']' expected");
3754 Parser.Lex(); // Eat right bracket token.
3755
3756 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbacha95ec992011-10-11 17:29:55 +00003757 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbachd3595712011-08-03 23:50:40 +00003758 S, E));
3759
Jim Grosbachc320c852011-08-05 21:28:30 +00003760 // If there's a pre-indexing writeback marker, '!', just add it as a token
3761 // operand.
3762 if (Parser.getTok().is(AsmToken::Exclaim)) {
3763 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3764 Parser.Lex(); // Eat the '!'.
3765 }
Jim Grosbachd3595712011-08-03 23:50:40 +00003766
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003767 return false;
3768}
3769
Jim Grosbachd3595712011-08-03 23:50:40 +00003770/// parseMemRegOffsetShift - one of these two:
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003771/// ( lsl | lsr | asr | ror ) , # shift_amount
3772/// rrx
Jim Grosbachd3595712011-08-03 23:50:40 +00003773/// return true if it parses a shift otherwise it returns false.
3774bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
3775 unsigned &Amount) {
3776 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan936b0d32010-01-19 21:44:56 +00003777 const AsmToken &Tok = Parser.getTok();
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003778 if (Tok.isNot(AsmToken::Identifier))
3779 return true;
Benjamin Kramer92d89982010-07-14 22:38:02 +00003780 StringRef ShiftName = Tok.getString();
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003781 if (ShiftName == "lsl" || ShiftName == "LSL")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003782 St = ARM_AM::lsl;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003783 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003784 St = ARM_AM::lsr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003785 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003786 St = ARM_AM::asr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003787 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003788 St = ARM_AM::ror;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003789 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003790 St = ARM_AM::rrx;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003791 else
Jim Grosbachd3595712011-08-03 23:50:40 +00003792 return Error(Loc, "illegal shift operator");
Sean Callanana83fd7d2010-01-19 20:27:46 +00003793 Parser.Lex(); // Eat shift type token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003794
Jim Grosbachd3595712011-08-03 23:50:40 +00003795 // rrx stands alone.
3796 Amount = 0;
3797 if (St != ARM_AM::rrx) {
3798 Loc = Parser.getTok().getLoc();
3799 // A '#' and a shift amount.
3800 const AsmToken &HashTok = Parser.getTok();
3801 if (HashTok.isNot(AsmToken::Hash))
3802 return Error(HashTok.getLoc(), "'#' expected");
3803 Parser.Lex(); // Eat hash token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003804
Jim Grosbachd3595712011-08-03 23:50:40 +00003805 const MCExpr *Expr;
3806 if (getParser().ParseExpression(Expr))
3807 return true;
3808 // Range check the immediate.
3809 // lsl, ror: 0 <= imm <= 31
3810 // lsr, asr: 0 <= imm <= 32
3811 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3812 if (!CE)
3813 return Error(Loc, "shift amount must be an immediate");
3814 int64_t Imm = CE->getValue();
3815 if (Imm < 0 ||
3816 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
3817 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
3818 return Error(Loc, "immediate shift value out of range");
3819 Amount = Imm;
3820 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003821
3822 return false;
3823}
3824
Jim Grosbache7fbce72011-10-03 23:38:36 +00003825/// parseFPImm - A floating point immediate expression operand.
3826ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3827parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3828 SMLoc S = Parser.getTok().getLoc();
3829
3830 if (Parser.getTok().isNot(AsmToken::Hash))
3831 return MatchOperand_NoMatch;
Jim Grosbach741cd732011-10-17 22:26:03 +00003832
3833 // Disambiguate the VMOV forms that can accept an FP immediate.
3834 // vmov.f32 <sreg>, #imm
3835 // vmov.f64 <dreg>, #imm
3836 // vmov.f32 <dreg>, #imm @ vector f32x2
3837 // vmov.f32 <qreg>, #imm @ vector f32x4
3838 //
3839 // There are also the NEON VMOV instructions which expect an
3840 // integer constant. Make sure we don't try to parse an FPImm
3841 // for these:
3842 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
3843 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
3844 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
3845 TyOp->getToken() != ".f64"))
3846 return MatchOperand_NoMatch;
3847
Jim Grosbache7fbce72011-10-03 23:38:36 +00003848 Parser.Lex(); // Eat the '#'.
3849
3850 // Handle negation, as that still comes through as a separate token.
3851 bool isNegative = false;
3852 if (Parser.getTok().is(AsmToken::Minus)) {
3853 isNegative = true;
3854 Parser.Lex();
3855 }
3856 const AsmToken &Tok = Parser.getTok();
3857 if (Tok.is(AsmToken::Real)) {
3858 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
3859 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3860 // If we had a '-' in front, toggle the sign bit.
3861 IntVal ^= (uint64_t)isNegative << 63;
3862 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
3863 Parser.Lex(); // Eat the token.
3864 if (Val == -1) {
3865 TokError("floating point value out of range");
3866 return MatchOperand_ParseFail;
3867 }
3868 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3869 return MatchOperand_Success;
3870 }
3871 if (Tok.is(AsmToken::Integer)) {
3872 int64_t Val = Tok.getIntVal();
3873 Parser.Lex(); // Eat the token.
3874 if (Val > 255 || Val < 0) {
3875 TokError("encoded floating point value out of range");
3876 return MatchOperand_ParseFail;
3877 }
3878 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3879 return MatchOperand_Success;
3880 }
3881
3882 TokError("invalid floating point immediate");
3883 return MatchOperand_ParseFail;
3884}
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003885/// Parse a arm instruction operand. For now this parses the operand regardless
3886/// of the mnemonic.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003887bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003888 StringRef Mnemonic) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003889 SMLoc S, E;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003890
3891 // Check if the current operand has a custom associated parser, if so, try to
3892 // custom parse the operand, or fallback to the general approach.
Jim Grosbach861e49c2011-02-12 01:34:40 +00003893 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3894 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003895 return false;
Jim Grosbach861e49c2011-02-12 01:34:40 +00003896 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3897 // there was a match, but an error occurred, in which case, just return that
3898 // the operand parsing failed.
3899 if (ResTy == MatchOperand_ParseFail)
3900 return true;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003901
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003902 switch (getLexer().getKind()) {
Bill Wendlingee7f1f92010-11-06 21:42:12 +00003903 default:
3904 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling2063b842010-11-18 23:43:05 +00003905 return true;
Jim Grosbachbb24c592011-07-13 18:49:30 +00003906 case AsmToken::Identifier: {
Jim Grosbach4ab23b52011-10-03 21:12:43 +00003907 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003908 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling2063b842010-11-18 23:43:05 +00003909 return false;
Jim Grosbach0d6022d2011-07-26 20:41:24 +00003910 int Res = tryParseShiftRegister(Operands);
Jim Grosbachbb24c592011-07-13 18:49:30 +00003911 if (Res == 0) // success
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003912 return false;
Jim Grosbachbb24c592011-07-13 18:49:30 +00003913 else if (Res == -1) // irrecoverable error
3914 return true;
Jim Grosbach4ab23b52011-10-03 21:12:43 +00003915 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
3916 S = Parser.getTok().getLoc();
3917 Parser.Lex();
3918 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
3919 return false;
3920 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00003921
3922 // Fall though for the Identifier case that is not a register or a
3923 // special name.
Jim Grosbachbb24c592011-07-13 18:49:30 +00003924 }
Jim Grosbach4e380352011-10-26 21:14:08 +00003925 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderbyb084be92011-01-13 20:32:36 +00003926 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach5c6b6342011-11-01 22:38:31 +00003927 case AsmToken::String: // quoted label names.
Kevin Enderbyb084be92011-01-13 20:32:36 +00003928 case AsmToken::Dot: { // . as a branch target
Kevin Enderby146dcf22009-10-15 20:48:48 +00003929 // This was not a register so parse other operands that start with an
3930 // identifier (like labels) as expressions and create them as immediates.
3931 const MCExpr *IdVal;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003932 S = Parser.getTok().getLoc();
Kevin Enderby146dcf22009-10-15 20:48:48 +00003933 if (getParser().ParseExpression(IdVal))
Bill Wendling2063b842010-11-18 23:43:05 +00003934 return true;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003935 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling2063b842010-11-18 23:43:05 +00003936 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
3937 return false;
3938 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003939 case AsmToken::LBrac:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003940 return parseMemory(Operands);
Kevin Enderbya2b99102009-10-09 21:12:28 +00003941 case AsmToken::LCurly:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003942 return parseRegisterList(Operands);
Owen Andersonf02d98d2011-08-29 17:17:09 +00003943 case AsmToken::Hash: {
Kevin Enderby3a80dac2009-10-13 23:33:38 +00003944 // #42 -> immediate.
3945 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003946 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00003947 Parser.Lex();
Owen Andersonf02d98d2011-08-29 17:17:09 +00003948 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby146dcf22009-10-15 20:48:48 +00003949 const MCExpr *ImmVal;
3950 if (getParser().ParseExpression(ImmVal))
Bill Wendling2063b842010-11-18 23:43:05 +00003951 return true;
Owen Andersonf02d98d2011-08-29 17:17:09 +00003952 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbach7f1f3bd2011-11-01 22:37:37 +00003953 if (CE) {
3954 int32_t Val = CE->getValue();
3955 if (isNegative && Val == 0)
3956 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Andersonf02d98d2011-08-29 17:17:09 +00003957 }
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003958 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling2063b842010-11-18 23:43:05 +00003959 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
3960 return false;
Owen Andersonf02d98d2011-08-29 17:17:09 +00003961 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00003962 case AsmToken::Colon: {
3963 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng965b3c72011-01-13 07:58:56 +00003964 // FIXME: Check it's an expression prefix,
3965 // e.g. (FOO - :lower16:BAR) isn't legal.
3966 ARMMCExpr::VariantKind RefKind;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003967 if (parsePrefix(RefKind))
Jason W Kim1f7bc072011-01-11 23:53:41 +00003968 return true;
3969
Evan Cheng965b3c72011-01-13 07:58:56 +00003970 const MCExpr *SubExprVal;
3971 if (getParser().ParseExpression(SubExprVal))
Jason W Kim1f7bc072011-01-11 23:53:41 +00003972 return true;
3973
Evan Cheng965b3c72011-01-13 07:58:56 +00003974 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
3975 getContext());
Jason W Kim1f7bc072011-01-11 23:53:41 +00003976 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng965b3c72011-01-13 07:58:56 +00003977 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim1f7bc072011-01-11 23:53:41 +00003978 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003979 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00003980 }
3981}
3982
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003983// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng965b3c72011-01-13 07:58:56 +00003984// :lower16: and :upper16:.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003985bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng965b3c72011-01-13 07:58:56 +00003986 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim1f7bc072011-01-11 23:53:41 +00003987
3988 // :lower16: and :upper16: modifiers
Jason W Kim93229972011-01-13 00:27:00 +00003989 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim1f7bc072011-01-11 23:53:41 +00003990 Parser.Lex(); // Eat ':'
3991
3992 if (getLexer().isNot(AsmToken::Identifier)) {
3993 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
3994 return true;
3995 }
3996
3997 StringRef IDVal = Parser.getTok().getIdentifier();
3998 if (IDVal == "lower16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00003999 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00004000 } else if (IDVal == "upper16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00004001 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00004002 } else {
4003 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4004 return true;
4005 }
4006 Parser.Lex();
4007
4008 if (getLexer().isNot(AsmToken::Colon)) {
4009 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4010 return true;
4011 }
4012 Parser.Lex(); // Eat the last ':'
4013 return false;
4014}
4015
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004016/// \brief Given a mnemonic, split out possible predication code and carry
4017/// setting letters to form a canonical mnemonic and flags.
4018//
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004019// FIXME: Would be nice to autogen this.
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004020// FIXME: This is a bit of a maze of special cases.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004021StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00004022 unsigned &PredicationCode,
4023 bool &CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004024 unsigned &ProcessorIMod,
4025 StringRef &ITMask) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004026 PredicationCode = ARMCC::AL;
4027 CarrySetting = false;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004028 ProcessorIMod = 0;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004029
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004030 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004031 //
4032 // FIXME: Would be nice to autogen this.
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00004033 if ((Mnemonic == "movs" && isThumb()) ||
4034 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4035 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4036 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4037 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4038 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4039 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
4040 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004041 return Mnemonic;
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004042
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00004043 // First, split out any predication code. Ignore mnemonics we know aren't
4044 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbach8d114902011-07-20 18:20:31 +00004045 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach0c398b92011-07-27 21:58:11 +00004046 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach3636be32011-08-22 23:55:58 +00004047 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbachf6d5d602011-09-01 18:22:13 +00004048 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00004049 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4050 .Case("eq", ARMCC::EQ)
4051 .Case("ne", ARMCC::NE)
4052 .Case("hs", ARMCC::HS)
4053 .Case("cs", ARMCC::HS)
4054 .Case("lo", ARMCC::LO)
4055 .Case("cc", ARMCC::LO)
4056 .Case("mi", ARMCC::MI)
4057 .Case("pl", ARMCC::PL)
4058 .Case("vs", ARMCC::VS)
4059 .Case("vc", ARMCC::VC)
4060 .Case("hi", ARMCC::HI)
4061 .Case("ls", ARMCC::LS)
4062 .Case("ge", ARMCC::GE)
4063 .Case("lt", ARMCC::LT)
4064 .Case("gt", ARMCC::GT)
4065 .Case("le", ARMCC::LE)
4066 .Case("al", ARMCC::AL)
4067 .Default(~0U);
4068 if (CC != ~0U) {
4069 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4070 PredicationCode = CC;
4071 }
Bill Wendling193961b2010-10-29 23:50:21 +00004072 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004073
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004074 // Next, determine if we have a carry setting bit. We explicitly ignore all
4075 // the instructions we know end in 's'.
4076 if (Mnemonic.endswith("s") &&
Jim Grosbachd3e8e292011-08-17 22:49:09 +00004077 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00004078 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4079 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4080 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach51726e22011-07-29 20:26:09 +00004081 Mnemonic == "vrsqrts" || Mnemonic == "srs" ||
4082 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004083 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4084 CarrySetting = true;
4085 }
4086
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004087 // The "cps" instruction can have a interrupt mode operand which is glued into
4088 // the mnemonic. Check if this is the case, split it and parse the imod op
4089 if (Mnemonic.startswith("cps")) {
4090 // Split out any imod code.
4091 unsigned IMod =
4092 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4093 .Case("ie", ARM_PROC::IE)
4094 .Case("id", ARM_PROC::ID)
4095 .Default(~0U);
4096 if (IMod != ~0U) {
4097 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4098 ProcessorIMod = IMod;
4099 }
4100 }
4101
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004102 // The "it" instruction has the condition mask on the end of the mnemonic.
4103 if (Mnemonic.startswith("it")) {
4104 ITMask = Mnemonic.slice(2, Mnemonic.size());
4105 Mnemonic = Mnemonic.slice(0, 2);
4106 }
4107
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004108 return Mnemonic;
4109}
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004110
4111/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4112/// inclusion of carry set or predication code operands.
4113//
4114// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00004115void ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004116getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00004117 bool &CanAcceptPredicationCode) {
Daniel Dunbar09264122011-01-11 19:06:29 +00004118 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4119 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00004120 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00004121 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004122 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00004123 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004124 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00004125 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004126 Mnemonic == "mla" || Mnemonic == "smlal" ||
4127 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbar09264122011-01-11 19:06:29 +00004128 CanAcceptCarrySet = true;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004129 } else
Daniel Dunbar09264122011-01-11 19:06:29 +00004130 CanAcceptCarrySet = false;
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004131
Daniel Dunbar09264122011-01-11 19:06:29 +00004132 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4133 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4134 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4135 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbach803898f2011-09-06 20:27:04 +00004136 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4137 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach25977222011-08-19 23:24:36 +00004138 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach93981412011-10-11 21:55:36 +00004139 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4140 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4141 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbachb9d4e372011-08-26 22:21:51 +00004142 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4143 !isThumb()) ||
Jim Grosbachb908b7a2011-09-10 00:15:36 +00004144 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004145 CanAcceptPredicationCode = false;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004146 } else
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004147 CanAcceptPredicationCode = true;
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004148
Jim Grosbach6c45b752011-09-16 16:39:25 +00004149 if (isThumb()) {
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004150 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbachb98ab912011-06-30 22:10:46 +00004151 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004152 CanAcceptPredicationCode = false;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004153 }
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004154}
4155
Jim Grosbach7283da92011-08-16 21:12:37 +00004156bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4157 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004158 // FIXME: This is all horribly hacky. We really need a better way to deal
4159 // with optional operands like this in the matcher table.
Jim Grosbach7283da92011-08-16 21:12:37 +00004160
4161 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4162 // another does not. Specifically, the MOVW instruction does not. So we
4163 // special case it here and remove the defaulted (non-setting) cc_out
4164 // operand if that's the instruction we're trying to match.
4165 //
4166 // We do this as post-processing of the explicit operands rather than just
4167 // conditionally adding the cc_out in the first place because we need
4168 // to check the type of the parsed immediate operand.
Owen Andersond7791b92011-09-14 22:46:14 +00004169 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbach7283da92011-08-16 21:12:37 +00004170 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4171 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4172 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4173 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00004174
4175 // Register-register 'add' for thumb does not have a cc_out operand
4176 // when there are only two register operands.
4177 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4178 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4179 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4180 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4181 return true;
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004182 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004183 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4184 // have to check the immediate range here since Thumb2 has a variant
4185 // that can handle a different range and has a cc_out operand.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004186 if (((isThumb() && Mnemonic == "add") ||
4187 (isThumbTwo() && Mnemonic == "sub")) &&
4188 Operands.size() == 6 &&
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004189 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4190 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4191 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004192 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4193 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4194 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004195 return true;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004196 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4197 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004198 // selecting via the generic "add" mnemonic, so to know that we
4199 // should remove the cc_out operand, we have to explicitly check that
4200 // it's not one of the other variants. Ugh.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004201 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4202 Operands.size() == 6 &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004203 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4204 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4205 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4206 // Nest conditions rather than one big 'if' statement for readability.
4207 //
4208 // If either register is a high reg, it's either one of the SP
4209 // variants (handled above) or a 32-bit encoding, so we just
4210 // check against T3.
4211 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4212 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4213 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4214 return false;
4215 // If both registers are low, we're in an IT block, and the immediate is
4216 // in range, we should use encoding T1 instead, which has a cc_out.
4217 if (inITBlock() &&
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004218 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004219 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4220 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4221 return false;
4222
4223 // Otherwise, we use encoding T4, which does not have a cc_out
4224 // operand.
4225 return true;
4226 }
4227
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004228 // The thumb2 multiply instruction doesn't have a CCOut register, so
4229 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4230 // use the 16-bit encoding or not.
4231 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4232 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4233 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4234 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4235 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4236 // If the registers aren't low regs, the destination reg isn't the
4237 // same as one of the source regs, or the cc_out operand is zero
4238 // outside of an IT block, we have to use the 32-bit encoding, so
4239 // remove the cc_out operand.
4240 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4241 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach6efa7b92011-11-15 19:29:45 +00004242 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004243 !inITBlock() ||
4244 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4245 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4246 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4247 static_cast<ARMOperand*>(Operands[4])->getReg())))
4248 return true;
4249
Jim Grosbachefa7e952011-11-15 19:55:16 +00004250 // Also check the 'mul' syntax variant that doesn't specify an explicit
4251 // destination register.
4252 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4253 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4254 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4255 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4256 // If the registers aren't low regs or the cc_out operand is zero
4257 // outside of an IT block, we have to use the 32-bit encoding, so
4258 // remove the cc_out operand.
4259 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4260 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4261 !inITBlock()))
4262 return true;
4263
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004264
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004265
Jim Grosbach4b701af2011-08-24 21:42:27 +00004266 // Register-register 'add/sub' for thumb does not have a cc_out operand
4267 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4268 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4269 // right, this will result in better diagnostics (which operand is off)
4270 // anyway.
4271 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4272 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004273 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4274 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4275 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4276 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00004277
Jim Grosbach7283da92011-08-16 21:12:37 +00004278 return false;
4279}
4280
Jim Grosbach12952fe2011-11-11 23:08:10 +00004281static bool isDataTypeToken(StringRef Tok) {
4282 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4283 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4284 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4285 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4286 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4287 Tok == ".f" || Tok == ".d";
4288}
4289
4290// FIXME: This bit should probably be handled via an explicit match class
4291// in the .td files that matches the suffix instead of having it be
4292// a literal string token the way it is now.
4293static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4294 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4295}
4296
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004297/// Parse an arm instruction mnemonic followed by its operands.
4298bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4299 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4300 // Create the leading tokens for the mnemonic, split by '.' characters.
4301 size_t Start = 0, Next = Name.find('.');
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004302 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004303
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004304 // Split out the predication code and carry setting flag from the mnemonic.
4305 unsigned PredicationCode;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004306 unsigned ProcessorIMod;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004307 bool CarrySetting;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004308 StringRef ITMask;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004309 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004310 ProcessorIMod, ITMask);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004311
Jim Grosbach1c171b12011-08-25 17:23:55 +00004312 // In Thumb1, only the branch (B) instruction can be predicated.
4313 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4314 Parser.EatToEndOfStatement();
4315 return Error(NameLoc, "conditional execution not supported in Thumb1");
4316 }
4317
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004318 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4319
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004320 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4321 // is the mask as it will be for the IT encoding if the conditional
4322 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4323 // where the conditional bit0 is zero, the instruction post-processing
4324 // will adjust the mask accordingly.
4325 if (Mnemonic == "it") {
Jim Grosbached16ec42011-08-29 22:24:09 +00004326 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4327 if (ITMask.size() > 3) {
4328 Parser.EatToEndOfStatement();
4329 return Error(Loc, "too many conditions on IT instruction");
4330 }
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004331 unsigned Mask = 8;
4332 for (unsigned i = ITMask.size(); i != 0; --i) {
4333 char pos = ITMask[i - 1];
4334 if (pos != 't' && pos != 'e') {
4335 Parser.EatToEndOfStatement();
Jim Grosbached16ec42011-08-29 22:24:09 +00004336 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004337 }
4338 Mask >>= 1;
4339 if (ITMask[i - 1] == 't')
4340 Mask |= 8;
4341 }
Jim Grosbached16ec42011-08-29 22:24:09 +00004342 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004343 }
4344
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004345 // FIXME: This is all a pretty gross hack. We should automatically handle
4346 // optional operands like this via tblgen.
Bill Wendling219dabd2010-11-21 10:56:05 +00004347
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004348 // Next, add the CCOut and ConditionCode operands, if needed.
4349 //
4350 // For mnemonics which can ever incorporate a carry setting bit or predication
4351 // code, our matching model involves us always generating CCOut and
4352 // ConditionCode operands to match the mnemonic "as written" and then we let
4353 // the matcher deal with finding the right instruction or generating an
4354 // appropriate error.
4355 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004356 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004357
Jim Grosbach03a8a162011-07-14 22:04:21 +00004358 // If we had a carry-set on an instruction that can't do that, issue an
4359 // error.
4360 if (!CanAcceptCarrySet && CarrySetting) {
4361 Parser.EatToEndOfStatement();
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004362 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach03a8a162011-07-14 22:04:21 +00004363 "' can not set flags, but 's' suffix specified");
4364 }
Jim Grosbach0a547702011-07-22 17:44:50 +00004365 // If we had a predication code on an instruction that can't do that, issue an
4366 // error.
4367 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4368 Parser.EatToEndOfStatement();
4369 return Error(NameLoc, "instruction '" + Mnemonic +
4370 "' is not predicable, but condition code specified");
4371 }
Jim Grosbach03a8a162011-07-14 22:04:21 +00004372
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004373 // Add the carry setting operand, if necessary.
Jim Grosbached16ec42011-08-29 22:24:09 +00004374 if (CanAcceptCarrySet) {
4375 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004376 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbached16ec42011-08-29 22:24:09 +00004377 Loc));
4378 }
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004379
4380 // Add the predication code operand, if necessary.
4381 if (CanAcceptPredicationCode) {
Jim Grosbached16ec42011-08-29 22:24:09 +00004382 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4383 CarrySetting);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004384 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbached16ec42011-08-29 22:24:09 +00004385 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004386 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004387
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004388 // Add the processor imod operand, if necessary.
4389 if (ProcessorIMod) {
4390 Operands.push_back(ARMOperand::CreateImm(
4391 MCConstantExpr::Create(ProcessorIMod, getContext()),
4392 NameLoc, NameLoc));
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004393 }
4394
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004395 // Add the remaining tokens in the mnemonic.
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004396 while (Next != StringRef::npos) {
4397 Start = Next;
4398 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004399 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004400
Jim Grosbach12952fe2011-11-11 23:08:10 +00004401 // Some NEON instructions have an optional datatype suffix that is
4402 // completely ignored. Check for that.
4403 if (isDataTypeToken(ExtraToken) &&
4404 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4405 continue;
4406
Jim Grosbach39c6e1d2011-09-07 16:06:04 +00004407 if (ExtraToken != ".n") {
4408 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4409 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4410 }
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004411 }
4412
4413 // Read the remaining operands.
4414 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004415 // Read the first operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004416 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnera2a9d162010-09-11 16:18:25 +00004417 Parser.EatToEndOfStatement();
4418 return true;
4419 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004420
4421 while (getLexer().is(AsmToken::Comma)) {
Sean Callanana83fd7d2010-01-19 20:27:46 +00004422 Parser.Lex(); // Eat the comma.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004423
4424 // Parse and remember the operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004425 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnera2a9d162010-09-11 16:18:25 +00004426 Parser.EatToEndOfStatement();
4427 return true;
4428 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004429 }
4430 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00004431
Chris Lattnera2a9d162010-09-11 16:18:25 +00004432 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbachb8d9f512011-10-07 18:27:04 +00004433 SMLoc Loc = getLexer().getLoc();
Chris Lattnera2a9d162010-09-11 16:18:25 +00004434 Parser.EatToEndOfStatement();
Jim Grosbachb8d9f512011-10-07 18:27:04 +00004435 return Error(Loc, "unexpected token in argument list");
Chris Lattnera2a9d162010-09-11 16:18:25 +00004436 }
Bill Wendlingee7f1f92010-11-06 21:42:12 +00004437
Chris Lattner91689c12010-09-08 05:10:46 +00004438 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004439
Jim Grosbach7283da92011-08-16 21:12:37 +00004440 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4441 // do and don't have a cc_out optional-def operand. With some spot-checks
4442 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004443 // parse and adjust accordingly before actually matching. We shouldn't ever
4444 // try to remove a cc_out operand that was explicitly set on the the
4445 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4446 // table driven matcher doesn't fit well with the ARM instruction set.
4447 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004448 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4449 Operands.erase(Operands.begin() + 1);
4450 delete Op;
4451 }
4452
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00004453 // ARM mode 'blx' need special handling, as the register operand version
4454 // is predicable, but the label operand version is not. So, we can't rely
4455 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach6e5778f2011-10-07 23:24:09 +00004456 // a k_CondCode operand in the list. If we're trying to match the label
4457 // version, remove the k_CondCode operand here.
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00004458 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4459 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4460 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4461 Operands.erase(Operands.begin() + 1);
4462 delete Op;
4463 }
Jim Grosbach8cffa282011-08-11 23:51:13 +00004464
4465 // The vector-compare-to-zero instructions have a literal token "#0" at
4466 // the end that comes to here as an immediate operand. Convert it to a
4467 // token to play nicely with the matcher.
4468 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4469 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4470 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4471 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4472 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4473 if (CE && CE->getValue() == 0) {
4474 Operands.erase(Operands.begin() + 5);
4475 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4476 delete Op;
4477 }
4478 }
Jim Grosbach46b66462011-10-03 22:30:24 +00004479 // VCMP{E} does the same thing, but with a different operand count.
4480 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4481 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4482 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4483 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4484 if (CE && CE->getValue() == 0) {
4485 Operands.erase(Operands.begin() + 4);
4486 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4487 delete Op;
4488 }
4489 }
Jim Grosbachc3c32d92011-08-22 23:47:13 +00004490 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
4491 // end. Convert it to a token here.
4492 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
4493 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4494 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4495 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4496 if (CE && CE->getValue() == 0) {
4497 Operands.erase(Operands.begin() + 5);
4498 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4499 delete Op;
4500 }
4501 }
4502
Chris Lattnerf29c0b62010-01-14 22:21:20 +00004503 return false;
Kevin Enderbyccab3172009-09-15 00:27:25 +00004504}
4505
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004506// Validate context-sensitive operand constraints.
Jim Grosbach169b2be2011-08-23 18:13:04 +00004507
4508// return 'true' if register list contains non-low GPR registers,
4509// 'false' otherwise. If Reg is in the register list or is HiReg, set
4510// 'containsReg' to true.
4511static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4512 unsigned HiReg, bool &containsReg) {
4513 containsReg = false;
4514 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4515 unsigned OpReg = Inst.getOperand(i).getReg();
4516 if (OpReg == Reg)
4517 containsReg = true;
4518 // Anything other than a low register isn't legal here.
4519 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4520 return true;
4521 }
4522 return false;
4523}
4524
Jim Grosbacha31f2232011-09-07 18:05:34 +00004525// Check if the specified regisgter is in the register list of the inst,
4526// starting at the indicated operand number.
4527static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4528 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4529 unsigned OpReg = Inst.getOperand(i).getReg();
4530 if (OpReg == Reg)
4531 return true;
4532 }
4533 return false;
4534}
4535
Jim Grosbached16ec42011-08-29 22:24:09 +00004536// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4537// the ARMInsts array) instead. Getting that here requires awkward
4538// API changes, though. Better way?
4539namespace llvm {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00004540extern const MCInstrDesc ARMInsts[];
Jim Grosbached16ec42011-08-29 22:24:09 +00004541}
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00004542static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbached16ec42011-08-29 22:24:09 +00004543 return ARMInsts[Opcode];
4544}
4545
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004546// FIXME: We would really like to be able to tablegen'erate this.
4547bool ARMAsmParser::
4548validateInstruction(MCInst &Inst,
4549 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00004550 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbached16ec42011-08-29 22:24:09 +00004551 SMLoc Loc = Operands[0]->getStartLoc();
4552 // Check the IT block state first.
Owen Anderson44ae2da2011-09-13 17:59:19 +00004553 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4554 // being allowed in IT blocks, but not being predicable. It just always
4555 // executes.
4556 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbached16ec42011-08-29 22:24:09 +00004557 unsigned bit = 1;
4558 if (ITState.FirstCond)
4559 ITState.FirstCond = false;
4560 else
Jim Grosbacha0d34d32011-09-02 23:22:08 +00004561 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbached16ec42011-08-29 22:24:09 +00004562 // The instruction must be predicable.
4563 if (!MCID.isPredicable())
4564 return Error(Loc, "instructions in IT block must be predicable");
4565 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4566 unsigned ITCond = bit ? ITState.Cond :
4567 ARMCC::getOppositeCondition(ITState.Cond);
4568 if (Cond != ITCond) {
4569 // Find the condition code Operand to get its SMLoc information.
4570 SMLoc CondLoc;
4571 for (unsigned i = 1; i < Operands.size(); ++i)
4572 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4573 CondLoc = Operands[i]->getStartLoc();
4574 return Error(CondLoc, "incorrect condition in IT block; got '" +
4575 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4576 "', but expected '" +
4577 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4578 }
Jim Grosbachc61fc8f2011-08-31 18:29:05 +00004579 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00004580 } else if (isThumbTwo() && MCID.isPredicable() &&
4581 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson29cfe6c2011-09-09 21:48:23 +00004582 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4583 Inst.getOpcode() != ARM::t2B)
Jim Grosbached16ec42011-08-29 22:24:09 +00004584 return Error(Loc, "predicated instructions must be in IT block");
4585
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004586 switch (Inst.getOpcode()) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00004587 case ARM::LDRD:
4588 case ARM::LDRD_PRE:
4589 case ARM::LDRD_POST:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004590 case ARM::LDREXD: {
4591 // Rt2 must be Rt + 1.
4592 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4593 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4594 if (Rt2 != Rt + 1)
4595 return Error(Operands[3]->getStartLoc(),
4596 "destination operands must be sequential");
4597 return false;
4598 }
Jim Grosbacheb09f492011-08-11 20:28:23 +00004599 case ARM::STRD: {
4600 // Rt2 must be Rt + 1.
4601 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4602 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4603 if (Rt2 != Rt + 1)
4604 return Error(Operands[3]->getStartLoc(),
4605 "source operands must be sequential");
4606 return false;
4607 }
Jim Grosbachf7164b22011-08-10 20:49:18 +00004608 case ARM::STRD_PRE:
4609 case ARM::STRD_POST:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004610 case ARM::STREXD: {
4611 // Rt2 must be Rt + 1.
4612 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4613 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
4614 if (Rt2 != Rt + 1)
Jim Grosbacheb09f492011-08-11 20:28:23 +00004615 return Error(Operands[3]->getStartLoc(),
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004616 "source operands must be sequential");
4617 return false;
4618 }
Jim Grosbach03f56d92011-07-27 21:09:25 +00004619 case ARM::SBFX:
4620 case ARM::UBFX: {
4621 // width must be in range [1, 32-lsb]
4622 unsigned lsb = Inst.getOperand(2).getImm();
4623 unsigned widthm1 = Inst.getOperand(3).getImm();
4624 if (widthm1 >= 32 - lsb)
4625 return Error(Operands[5]->getStartLoc(),
4626 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach64610e52011-08-16 21:42:31 +00004627 return false;
Jim Grosbach03f56d92011-07-27 21:09:25 +00004628 }
Jim Grosbach90103cc2011-08-18 21:50:53 +00004629 case ARM::tLDMIA: {
Jim Grosbacha31f2232011-09-07 18:05:34 +00004630 // If we're parsing Thumb2, the .w variant is available and handles
4631 // most cases that are normally illegal for a Thumb1 LDM
4632 // instruction. We'll make the transformation in processInstruction()
4633 // if necessary.
4634 //
Jim Grosbach90103cc2011-08-18 21:50:53 +00004635 // Thumb LDM instructions are writeback iff the base register is not
4636 // in the register list.
4637 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach139acd22011-08-22 23:01:07 +00004638 bool hasWritebackToken =
4639 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4640 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbach169b2be2011-08-23 18:13:04 +00004641 bool listContainsBase;
Jim Grosbacha31f2232011-09-07 18:05:34 +00004642 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00004643 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4644 "registers must be in range r0-r7");
Jim Grosbach90103cc2011-08-18 21:50:53 +00004645 // If we should have writeback, then there should be a '!' token.
Jim Grosbacha31f2232011-09-07 18:05:34 +00004646 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach90103cc2011-08-18 21:50:53 +00004647 return Error(Operands[2]->getStartLoc(),
4648 "writeback operator '!' expected");
Jim Grosbacha31f2232011-09-07 18:05:34 +00004649 // If we should not have writeback, there must not be a '!'. This is
4650 // true even for the 32-bit wide encodings.
Jim Grosbach169b2be2011-08-23 18:13:04 +00004651 if (listContainsBase && hasWritebackToken)
Jim Grosbach139acd22011-08-22 23:01:07 +00004652 return Error(Operands[3]->getStartLoc(),
4653 "writeback operator '!' not allowed when base register "
4654 "in register list");
Jim Grosbach90103cc2011-08-18 21:50:53 +00004655
4656 break;
4657 }
Jim Grosbacha31f2232011-09-07 18:05:34 +00004658 case ARM::t2LDMIA_UPD: {
4659 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
4660 return Error(Operands[4]->getStartLoc(),
4661 "writeback operator '!' not allowed when base register "
4662 "in register list");
4663 break;
4664 }
Jim Grosbach9bded9d2011-11-10 23:17:11 +00004665 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
4666 // so only issue a diagnostic for thumb1. The instructions will be
4667 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach38c59fc2011-08-22 23:17:34 +00004668 case ARM::tPOP: {
Jim Grosbach169b2be2011-08-23 18:13:04 +00004669 bool listContainsBase;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00004670 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
4671 !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00004672 return Error(Operands[2]->getStartLoc(),
4673 "registers must be in range r0-r7 or pc");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00004674 break;
4675 }
4676 case ARM::tPUSH: {
Jim Grosbach169b2be2011-08-23 18:13:04 +00004677 bool listContainsBase;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00004678 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
4679 !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00004680 return Error(Operands[2]->getStartLoc(),
4681 "registers must be in range r0-r7 or lr");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00004682 break;
4683 }
Jim Grosbachd80d1692011-08-23 18:15:37 +00004684 case ARM::tSTMIA_UPD: {
4685 bool listContainsBase;
Jim Grosbach099c9762011-09-16 20:50:13 +00004686 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachd80d1692011-08-23 18:15:37 +00004687 return Error(Operands[4]->getStartLoc(),
4688 "registers must be in range r0-r7");
4689 break;
4690 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004691 }
4692
4693 return false;
4694}
4695
Jim Grosbachafad0532011-11-10 23:42:14 +00004696bool ARMAsmParser::
Jim Grosbach8ba76c62011-08-11 17:35:48 +00004697processInstruction(MCInst &Inst,
4698 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4699 switch (Inst.getOpcode()) {
Jim Grosbach61db5a52011-11-10 16:44:55 +00004700 // Handle the MOV complex aliases.
Jim Grosbachabcac562011-11-16 18:31:45 +00004701 case ARM::ASRr:
4702 case ARM::LSRr:
4703 case ARM::LSLr:
4704 case ARM::RORr: {
4705 ARM_AM::ShiftOpc ShiftTy;
4706 switch(Inst.getOpcode()) {
4707 default: llvm_unreachable("unexpected opcode!");
4708 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
4709 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
4710 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
4711 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
4712 }
4713 // A shift by zero is a plain MOVr, not a MOVsi.
4714 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
4715 MCInst TmpInst;
4716 TmpInst.setOpcode(ARM::MOVsr);
4717 TmpInst.addOperand(Inst.getOperand(0)); // Rd
4718 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4719 TmpInst.addOperand(Inst.getOperand(2)); // Rm
4720 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
4721 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
4722 TmpInst.addOperand(Inst.getOperand(4));
4723 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
4724 Inst = TmpInst;
4725 return true;
4726 }
Jim Grosbachc14871c2011-11-10 19:18:01 +00004727 case ARM::ASRi:
4728 case ARM::LSRi:
4729 case ARM::LSLi:
4730 case ARM::RORi: {
4731 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachc14871c2011-11-10 19:18:01 +00004732 switch(Inst.getOpcode()) {
4733 default: llvm_unreachable("unexpected opcode!");
4734 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
4735 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
4736 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
4737 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
4738 }
4739 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach1a2f9ee2011-11-16 19:05:59 +00004740 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachc14871c2011-11-10 19:18:01 +00004741 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
4742 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach61db5a52011-11-10 16:44:55 +00004743 MCInst TmpInst;
Jim Grosbachc14871c2011-11-10 19:18:01 +00004744 TmpInst.setOpcode(Opc);
Jim Grosbach61db5a52011-11-10 16:44:55 +00004745 TmpInst.addOperand(Inst.getOperand(0)); // Rd
4746 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachc14871c2011-11-10 19:18:01 +00004747 if (Opc == ARM::MOVsi)
4748 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach61db5a52011-11-10 16:44:55 +00004749 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
4750 TmpInst.addOperand(Inst.getOperand(4));
4751 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
4752 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00004753 return true;
Jim Grosbach61db5a52011-11-10 16:44:55 +00004754 }
Jim Grosbach1a2f9ee2011-11-16 19:05:59 +00004755 case ARM::RRXi: {
4756 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
4757 MCInst TmpInst;
4758 TmpInst.setOpcode(ARM::MOVsi);
4759 TmpInst.addOperand(Inst.getOperand(0)); // Rd
4760 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4761 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
4762 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4763 TmpInst.addOperand(Inst.getOperand(3));
4764 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
4765 Inst = TmpInst;
4766 return true;
4767 }
Jim Grosbachd9a9be22011-11-10 23:58:34 +00004768 case ARM::t2LDMIA_UPD: {
4769 // If this is a load of a single register, then we should use
4770 // a post-indexed LDR instruction instead, per the ARM ARM.
4771 if (Inst.getNumOperands() != 5)
4772 return false;
4773 MCInst TmpInst;
4774 TmpInst.setOpcode(ARM::t2LDR_POST);
4775 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4776 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4777 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4778 TmpInst.addOperand(MCOperand::CreateImm(4));
4779 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4780 TmpInst.addOperand(Inst.getOperand(3));
4781 Inst = TmpInst;
4782 return true;
4783 }
4784 case ARM::t2STMDB_UPD: {
4785 // If this is a store of a single register, then we should use
4786 // a pre-indexed STR instruction instead, per the ARM ARM.
4787 if (Inst.getNumOperands() != 5)
4788 return false;
4789 MCInst TmpInst;
4790 TmpInst.setOpcode(ARM::t2STR_PRE);
4791 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4792 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4793 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4794 TmpInst.addOperand(MCOperand::CreateImm(-4));
4795 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4796 TmpInst.addOperand(Inst.getOperand(3));
4797 Inst = TmpInst;
4798 return true;
4799 }
Jim Grosbach8ba76c62011-08-11 17:35:48 +00004800 case ARM::LDMIA_UPD:
4801 // If this is a load of a single register via a 'pop', then we should use
4802 // a post-indexed LDR instruction instead, per the ARM ARM.
4803 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
4804 Inst.getNumOperands() == 5) {
4805 MCInst TmpInst;
4806 TmpInst.setOpcode(ARM::LDR_POST_IMM);
4807 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4808 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4809 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4810 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
4811 TmpInst.addOperand(MCOperand::CreateImm(4));
4812 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4813 TmpInst.addOperand(Inst.getOperand(3));
4814 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00004815 return true;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00004816 }
4817 break;
Jim Grosbach27ad83d2011-08-11 18:07:11 +00004818 case ARM::STMDB_UPD:
4819 // If this is a store of a single register via a 'push', then we should use
4820 // a pre-indexed STR instruction instead, per the ARM ARM.
4821 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
4822 Inst.getNumOperands() == 5) {
4823 MCInst TmpInst;
4824 TmpInst.setOpcode(ARM::STR_PRE_IMM);
4825 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4826 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4827 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
4828 TmpInst.addOperand(MCOperand::CreateImm(-4));
4829 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4830 TmpInst.addOperand(Inst.getOperand(3));
4831 Inst = TmpInst;
4832 }
4833 break;
Jim Grosbache9ab47a2011-08-16 23:57:34 +00004834 case ARM::tADDi8:
Jim Grosbach6d606fb2011-08-31 17:07:33 +00004835 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4836 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4837 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4838 // to encoding T1 if <Rd> is omitted."
Jim Grosbachafad0532011-11-10 23:42:14 +00004839 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbache9ab47a2011-08-16 23:57:34 +00004840 Inst.setOpcode(ARM::tADDi3);
Jim Grosbachafad0532011-11-10 23:42:14 +00004841 return true;
4842 }
Jim Grosbache9ab47a2011-08-16 23:57:34 +00004843 break;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004844 case ARM::tSUBi8:
4845 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4846 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4847 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4848 // to encoding T1 if <Rd> is omitted."
Jim Grosbachafad0532011-11-10 23:42:14 +00004849 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004850 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbachafad0532011-11-10 23:42:14 +00004851 return true;
4852 }
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004853 break;
Owen Anderson29cfe6c2011-09-09 21:48:23 +00004854 case ARM::tB:
4855 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbachafad0532011-11-10 23:42:14 +00004856 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson29cfe6c2011-09-09 21:48:23 +00004857 Inst.setOpcode(ARM::tBcc);
Jim Grosbachafad0532011-11-10 23:42:14 +00004858 return true;
4859 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00004860 break;
4861 case ARM::t2B:
4862 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbachafad0532011-11-10 23:42:14 +00004863 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson29cfe6c2011-09-09 21:48:23 +00004864 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbachafad0532011-11-10 23:42:14 +00004865 return true;
4866 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00004867 break;
Jim Grosbach99bc8462011-08-31 21:17:31 +00004868 case ARM::t2Bcc:
Jim Grosbacha0d34d32011-09-02 23:22:08 +00004869 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbachafad0532011-11-10 23:42:14 +00004870 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbach99bc8462011-08-31 21:17:31 +00004871 Inst.setOpcode(ARM::t2B);
Jim Grosbachafad0532011-11-10 23:42:14 +00004872 return true;
4873 }
Jim Grosbach99bc8462011-08-31 21:17:31 +00004874 break;
Jim Grosbachcbd4ab12011-08-17 22:57:40 +00004875 case ARM::tBcc:
4876 // If the conditional is AL, we really want tB.
Jim Grosbachafad0532011-11-10 23:42:14 +00004877 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbachcbd4ab12011-08-17 22:57:40 +00004878 Inst.setOpcode(ARM::tB);
Jim Grosbachafad0532011-11-10 23:42:14 +00004879 return true;
4880 }
Jim Grosbach6ddb5682011-08-18 16:08:39 +00004881 break;
Jim Grosbacha31f2232011-09-07 18:05:34 +00004882 case ARM::tLDMIA: {
4883 // If the register list contains any high registers, or if the writeback
4884 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
4885 // instead if we're in Thumb2. Otherwise, this should have generated
4886 // an error in validateInstruction().
4887 unsigned Rn = Inst.getOperand(0).getReg();
4888 bool hasWritebackToken =
4889 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4890 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
4891 bool listContainsBase;
4892 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
4893 (!listContainsBase && !hasWritebackToken) ||
4894 (listContainsBase && hasWritebackToken)) {
4895 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4896 assert (isThumbTwo());
4897 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
4898 // If we're switching to the updating version, we need to insert
4899 // the writeback tied operand.
4900 if (hasWritebackToken)
4901 Inst.insert(Inst.begin(),
4902 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbachafad0532011-11-10 23:42:14 +00004903 return true;
Jim Grosbacha31f2232011-09-07 18:05:34 +00004904 }
4905 break;
4906 }
Jim Grosbach099c9762011-09-16 20:50:13 +00004907 case ARM::tSTMIA_UPD: {
4908 // If the register list contains any high registers, we need to use
4909 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
4910 // should have generated an error in validateInstruction().
4911 unsigned Rn = Inst.getOperand(0).getReg();
4912 bool listContainsBase;
4913 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
4914 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4915 assert (isThumbTwo());
4916 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbachafad0532011-11-10 23:42:14 +00004917 return true;
Jim Grosbach099c9762011-09-16 20:50:13 +00004918 }
4919 break;
4920 }
Jim Grosbach9bded9d2011-11-10 23:17:11 +00004921 case ARM::tPOP: {
4922 bool listContainsBase;
4923 // If the register list contains any high registers, we need to use
4924 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
4925 // should have generated an error in validateInstruction().
4926 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbachafad0532011-11-10 23:42:14 +00004927 return false;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00004928 assert (isThumbTwo());
4929 Inst.setOpcode(ARM::t2LDMIA_UPD);
4930 // Add the base register and writeback operands.
4931 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
4932 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbachafad0532011-11-10 23:42:14 +00004933 return true;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00004934 }
4935 case ARM::tPUSH: {
4936 bool listContainsBase;
4937 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbachafad0532011-11-10 23:42:14 +00004938 return false;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00004939 assert (isThumbTwo());
4940 Inst.setOpcode(ARM::t2STMDB_UPD);
4941 // Add the base register and writeback operands.
4942 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
4943 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbachafad0532011-11-10 23:42:14 +00004944 return true;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00004945 }
Jim Grosbachb908b7a2011-09-10 00:15:36 +00004946 case ARM::t2MOVi: {
4947 // If we can use the 16-bit encoding and the user didn't explicitly
4948 // request the 32-bit variant, transform it here.
4949 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4950 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbach18b8b172011-09-14 19:12:11 +00004951 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
4952 Inst.getOperand(4).getReg() == ARM::CPSR) ||
4953 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbachb908b7a2011-09-10 00:15:36 +00004954 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4955 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4956 // The operands aren't in the same order for tMOVi8...
4957 MCInst TmpInst;
4958 TmpInst.setOpcode(ARM::tMOVi8);
4959 TmpInst.addOperand(Inst.getOperand(0));
4960 TmpInst.addOperand(Inst.getOperand(4));
4961 TmpInst.addOperand(Inst.getOperand(1));
4962 TmpInst.addOperand(Inst.getOperand(2));
4963 TmpInst.addOperand(Inst.getOperand(3));
4964 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00004965 return true;
Jim Grosbachb908b7a2011-09-10 00:15:36 +00004966 }
4967 break;
4968 }
4969 case ARM::t2MOVr: {
4970 // If we can use the 16-bit encoding and the user didn't explicitly
4971 // request the 32-bit variant, transform it here.
4972 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4973 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4974 Inst.getOperand(2).getImm() == ARMCC::AL &&
4975 Inst.getOperand(4).getReg() == ARM::CPSR &&
4976 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4977 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4978 // The operands aren't the same for tMOV[S]r... (no cc_out)
4979 MCInst TmpInst;
4980 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
4981 TmpInst.addOperand(Inst.getOperand(0));
4982 TmpInst.addOperand(Inst.getOperand(1));
4983 TmpInst.addOperand(Inst.getOperand(2));
4984 TmpInst.addOperand(Inst.getOperand(3));
4985 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00004986 return true;
Jim Grosbachb908b7a2011-09-10 00:15:36 +00004987 }
4988 break;
4989 }
Jim Grosbach82213192011-09-19 20:29:33 +00004990 case ARM::t2SXTH:
Jim Grosbachb3519802011-09-20 00:46:54 +00004991 case ARM::t2SXTB:
4992 case ARM::t2UXTH:
4993 case ARM::t2UXTB: {
Jim Grosbach82213192011-09-19 20:29:33 +00004994 // If we can use the 16-bit encoding and the user didn't explicitly
4995 // request the 32-bit variant, transform it here.
4996 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4997 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4998 Inst.getOperand(2).getImm() == 0 &&
4999 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5000 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbachb3519802011-09-20 00:46:54 +00005001 unsigned NewOpc;
5002 switch (Inst.getOpcode()) {
5003 default: llvm_unreachable("Illegal opcode!");
5004 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
5005 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
5006 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
5007 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
5008 }
Jim Grosbach82213192011-09-19 20:29:33 +00005009 // The operands aren't the same for thumb1 (no rotate operand).
5010 MCInst TmpInst;
5011 TmpInst.setOpcode(NewOpc);
5012 TmpInst.addOperand(Inst.getOperand(0));
5013 TmpInst.addOperand(Inst.getOperand(1));
5014 TmpInst.addOperand(Inst.getOperand(3));
5015 TmpInst.addOperand(Inst.getOperand(4));
5016 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00005017 return true;
Jim Grosbach82213192011-09-19 20:29:33 +00005018 }
5019 break;
5020 }
Jim Grosbach3d1eac82011-08-26 21:43:41 +00005021 case ARM::t2IT: {
5022 // The mask bits for all but the first condition are represented as
5023 // the low bit of the condition code value implies 't'. We currently
5024 // always have 1 implies 't', so XOR toggle the bits if the low bit
5025 // of the condition code is zero. The encoding also expects the low
5026 // bit of the condition to be encoded as bit 4 of the mask operand,
5027 // so mask that in if needed
5028 MCOperand &MO = Inst.getOperand(1);
5029 unsigned Mask = MO.getImm();
Jim Grosbached16ec42011-08-29 22:24:09 +00005030 unsigned OrigMask = Mask;
5031 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00005032 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach3d1eac82011-08-26 21:43:41 +00005033 assert(Mask && TZ <= 3 && "illegal IT mask value!");
5034 for (unsigned i = 3; i != TZ; --i)
5035 Mask ^= 1 << i;
5036 } else
5037 Mask |= 0x10;
5038 MO.setImm(Mask);
Jim Grosbached16ec42011-08-29 22:24:09 +00005039
5040 // Set up the IT block state according to the IT instruction we just
5041 // matched.
5042 assert(!inITBlock() && "nested IT blocks?!");
5043 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
5044 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
5045 ITState.CurPosition = 0;
5046 ITState.FirstCond = true;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00005047 break;
5048 }
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005049 }
Jim Grosbachafad0532011-11-10 23:42:14 +00005050 return false;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005051}
5052
Jim Grosbach3e941ae2011-08-16 20:45:50 +00005053unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
5054 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
5055 // suffix depending on whether they're in an IT block or not.
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00005056 unsigned Opc = Inst.getOpcode();
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00005057 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach3e941ae2011-08-16 20:45:50 +00005058 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
5059 assert(MCID.hasOptionalDef() &&
5060 "optionally flag setting instruction missing optional def operand");
5061 assert(MCID.NumOperands == Inst.getNumOperands() &&
5062 "operand count mismatch!");
5063 // Find the optional-def operand (cc_out).
5064 unsigned OpNo;
5065 for (OpNo = 0;
5066 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
5067 ++OpNo)
5068 ;
5069 // If we're parsing Thumb1, reject it completely.
5070 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
5071 return Match_MnemonicFail;
5072 // If we're parsing Thumb2, which form is legal depends on whether we're
5073 // in an IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00005074 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
5075 !inITBlock())
Jim Grosbach3e941ae2011-08-16 20:45:50 +00005076 return Match_RequiresITBlock;
Jim Grosbached16ec42011-08-29 22:24:09 +00005077 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
5078 inITBlock())
5079 return Match_RequiresNotITBlock;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00005080 }
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00005081 // Some high-register supporting Thumb1 encodings only allow both registers
5082 // to be from r0-r7 when in Thumb2.
5083 else if (Opc == ARM::tADDhirr && isThumbOne() &&
5084 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5085 isARMLowRegister(Inst.getOperand(2).getReg()))
5086 return Match_RequiresThumb2;
5087 // Others only require ARMv6 or later.
Jim Grosbachf86cd372011-08-19 20:46:54 +00005088 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00005089 isARMLowRegister(Inst.getOperand(0).getReg()) &&
5090 isARMLowRegister(Inst.getOperand(1).getReg()))
5091 return Match_RequiresV6;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00005092 return Match_Success;
5093}
5094
Chris Lattner9487de62010-10-28 21:28:01 +00005095bool ARMAsmParser::
5096MatchAndEmitInstruction(SMLoc IDLoc,
5097 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
5098 MCStreamer &Out) {
5099 MCInst Inst;
5100 unsigned ErrorInfo;
Jim Grosbach120a96a2011-08-15 23:03:29 +00005101 unsigned MatchResult;
Kevin Enderby3164a342010-12-09 19:19:43 +00005102 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby3164a342010-12-09 19:19:43 +00005103 switch (MatchResult) {
Jim Grosbach120a96a2011-08-15 23:03:29 +00005104 default: break;
Chris Lattnerd27b05e2010-10-28 21:41:58 +00005105 case Match_Success:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005106 // Context sensitive operand constraints aren't handled by the matcher,
5107 // so check them here.
Jim Grosbacha0d34d32011-09-02 23:22:08 +00005108 if (validateInstruction(Inst, Operands)) {
5109 // Still progress the IT block, otherwise one wrong condition causes
5110 // nasty cascading errors.
5111 forwardITPosition();
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005112 return true;
Jim Grosbacha0d34d32011-09-02 23:22:08 +00005113 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005114
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005115 // Some instructions need post-processing to, for example, tweak which
Jim Grosbachafad0532011-11-10 23:42:14 +00005116 // encoding is selected. Loop on it while changes happen so the
5117 // individual transformations can chain off each other. E.g.,
5118 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
5119 while (processInstruction(Inst, Operands))
5120 ;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005121
Jim Grosbacha0d34d32011-09-02 23:22:08 +00005122 // Only move forward at the very end so that everything in validate
5123 // and process gets a consistent answer about whether we're in an IT
5124 // block.
5125 forwardITPosition();
5126
Chris Lattner9487de62010-10-28 21:28:01 +00005127 Out.EmitInstruction(Inst);
5128 return false;
Chris Lattnerd27b05e2010-10-28 21:41:58 +00005129 case Match_MissingFeature:
5130 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
5131 return true;
5132 case Match_InvalidOperand: {
5133 SMLoc ErrorLoc = IDLoc;
5134 if (ErrorInfo != ~0U) {
5135 if (ErrorInfo >= Operands.size())
5136 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach624bcc72010-10-29 14:46:02 +00005137
Chris Lattnerd27b05e2010-10-28 21:41:58 +00005138 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
5139 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
5140 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00005141
Chris Lattnerd27b05e2010-10-28 21:41:58 +00005142 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattner9487de62010-10-28 21:28:01 +00005143 }
Chris Lattnerd27b05e2010-10-28 21:41:58 +00005144 case Match_MnemonicFail:
Jim Grosbach3e941ae2011-08-16 20:45:50 +00005145 return Error(IDLoc, "invalid instruction");
Daniel Dunbar66193402011-02-04 17:12:23 +00005146 case Match_ConversionFail:
Jim Grosbach8e048492011-08-19 22:07:46 +00005147 // The converter function will have already emited a diagnostic.
5148 return true;
Jim Grosbached16ec42011-08-29 22:24:09 +00005149 case Match_RequiresNotITBlock:
5150 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach3e941ae2011-08-16 20:45:50 +00005151 case Match_RequiresITBlock:
5152 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00005153 case Match_RequiresV6:
5154 return Error(IDLoc, "instruction variant requires ARMv6 or later");
5155 case Match_RequiresThumb2:
5156 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnerd27b05e2010-10-28 21:41:58 +00005157 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00005158
Eric Christopher91d7b902010-10-29 09:26:59 +00005159 llvm_unreachable("Implement any new match types added!");
Bill Wendlingee7f1f92010-11-06 21:42:12 +00005160 return true;
Chris Lattner9487de62010-10-28 21:28:01 +00005161}
5162
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005163/// parseDirective parses the arm specific directives
Kevin Enderbyccab3172009-09-15 00:27:25 +00005164bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
5165 StringRef IDVal = DirectiveID.getIdentifier();
5166 if (IDVal == ".word")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005167 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00005168 else if (IDVal == ".thumb")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005169 return parseDirectiveThumb(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00005170 else if (IDVal == ".thumb_func")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005171 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00005172 else if (IDVal == ".code")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005173 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00005174 else if (IDVal == ".syntax")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005175 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyccab3172009-09-15 00:27:25 +00005176 return true;
5177}
5178
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005179/// parseDirectiveWord
Kevin Enderbyccab3172009-09-15 00:27:25 +00005180/// ::= .word [ expression (, expression)* ]
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005181bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyccab3172009-09-15 00:27:25 +00005182 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5183 for (;;) {
5184 const MCExpr *Value;
5185 if (getParser().ParseExpression(Value))
5186 return true;
5187
Chris Lattnerc35681b2010-01-19 19:46:13 +00005188 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyccab3172009-09-15 00:27:25 +00005189
5190 if (getLexer().is(AsmToken::EndOfStatement))
5191 break;
Jim Grosbach624bcc72010-10-29 14:46:02 +00005192
Kevin Enderbyccab3172009-09-15 00:27:25 +00005193 // FIXME: Improve diagnostic.
5194 if (getLexer().isNot(AsmToken::Comma))
5195 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00005196 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00005197 }
5198 }
5199
Sean Callanana83fd7d2010-01-19 20:27:46 +00005200 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00005201 return false;
5202}
5203
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005204/// parseDirectiveThumb
Kevin Enderby146dcf22009-10-15 20:48:48 +00005205/// ::= .thumb
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005206bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby146dcf22009-10-15 20:48:48 +00005207 if (getLexer().isNot(AsmToken::EndOfStatement))
5208 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00005209 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00005210
5211 // TODO: set thumb mode
5212 // TODO: tell the MC streamer the mode
5213 // getParser().getStreamer().Emit???();
5214 return false;
5215}
5216
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005217/// parseDirectiveThumbFunc
Kevin Enderby146dcf22009-10-15 20:48:48 +00005218/// ::= .thumbfunc symbol_name
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005219bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00005220 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
5221 bool isMachO = MAI.hasSubsectionsViaSymbols();
5222 StringRef Name;
5223
5224 // Darwin asm has function name after .thumb_func direction
5225 // ELF doesn't
5226 if (isMachO) {
5227 const AsmToken &Tok = Parser.getTok();
5228 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
5229 return Error(L, "unexpected token in .thumb_func directive");
Jim Grosbach42ba6282011-11-10 20:48:53 +00005230 Name = Tok.getIdentifier();
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00005231 Parser.Lex(); // Consume the identifier token.
5232 }
5233
Jim Grosbach42ba6282011-11-10 20:48:53 +00005234 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby146dcf22009-10-15 20:48:48 +00005235 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00005236 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00005237
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00005238 // FIXME: assuming function name will be the line following .thumb_func
5239 if (!isMachO) {
Jim Grosbach42ba6282011-11-10 20:48:53 +00005240 Name = Parser.getTok().getIdentifier();
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00005241 }
5242
Jim Grosbachc6db8ce2010-11-05 22:33:53 +00005243 // Mark symbol as a thumb symbol.
5244 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
5245 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby146dcf22009-10-15 20:48:48 +00005246 return false;
5247}
5248
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005249/// parseDirectiveSyntax
Kevin Enderby146dcf22009-10-15 20:48:48 +00005250/// ::= .syntax unified | divided
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005251bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00005252 const AsmToken &Tok = Parser.getTok();
Kevin Enderby146dcf22009-10-15 20:48:48 +00005253 if (Tok.isNot(AsmToken::Identifier))
5254 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer92d89982010-07-14 22:38:02 +00005255 StringRef Mode = Tok.getString();
Duncan Sands257eba42010-06-29 13:04:35 +00005256 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callanana83fd7d2010-01-19 20:27:46 +00005257 Parser.Lex();
Duncan Sands257eba42010-06-29 13:04:35 +00005258 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderbye9f2f0c2011-01-27 23:22:36 +00005259 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby146dcf22009-10-15 20:48:48 +00005260 else
5261 return Error(L, "unrecognized syntax mode in .syntax directive");
5262
5263 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan936b0d32010-01-19 21:44:56 +00005264 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00005265 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00005266
5267 // TODO tell the MC streamer the mode
5268 // getParser().getStreamer().Emit???();
5269 return false;
5270}
5271
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005272/// parseDirectiveCode
Kevin Enderby146dcf22009-10-15 20:48:48 +00005273/// ::= .code 16 | 32
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005274bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00005275 const AsmToken &Tok = Parser.getTok();
Kevin Enderby146dcf22009-10-15 20:48:48 +00005276 if (Tok.isNot(AsmToken::Integer))
5277 return Error(L, "unexpected token in .code directive");
Sean Callanan936b0d32010-01-19 21:44:56 +00005278 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands257eba42010-06-29 13:04:35 +00005279 if (Val == 16)
Sean Callanana83fd7d2010-01-19 20:27:46 +00005280 Parser.Lex();
Duncan Sands257eba42010-06-29 13:04:35 +00005281 else if (Val == 32)
Sean Callanana83fd7d2010-01-19 20:27:46 +00005282 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00005283 else
5284 return Error(L, "invalid operand to .code directive");
5285
5286 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan936b0d32010-01-19 21:44:56 +00005287 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00005288 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00005289
Evan Cheng284b4672011-07-08 22:36:29 +00005290 if (Val == 16) {
Jim Grosbachf471ac32011-09-06 18:46:23 +00005291 if (!isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00005292 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00005293 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng284b4672011-07-08 22:36:29 +00005294 } else {
Jim Grosbachf471ac32011-09-06 18:46:23 +00005295 if (isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00005296 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00005297 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Cheng45543ba2011-07-08 22:49:55 +00005298 }
Jim Grosbach2db0ea02010-11-05 22:40:53 +00005299
Kevin Enderby146dcf22009-10-15 20:48:48 +00005300 return false;
5301}
5302
Sean Callanan643a5572010-04-07 20:29:34 +00005303extern "C" void LLVMInitializeARMAsmLexer();
5304
Kevin Enderby8be42bd2009-10-30 22:55:57 +00005305/// Force static initialization.
Kevin Enderbyccab3172009-09-15 00:27:25 +00005306extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng11424442011-07-26 00:24:13 +00005307 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
5308 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan643a5572010-04-07 20:29:34 +00005309 LLVMInitializeARMAsmLexer();
Kevin Enderbyccab3172009-09-15 00:27:25 +00005310}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00005311
Chris Lattner3e4582a2010-09-06 19:11:01 +00005312#define GET_REGISTER_MATCHER
5313#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00005314#include "ARMGenAsmMatcher.inc"