blob: c685a266b8ab2c07554a5e9b0b74702c3ce15a05 [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 Grosbach04945c42011-12-02 00:35:16 +000042enum VectorLaneTy { NoLanes, AllLanes, IndexedLane };
Jim Grosbachcd6f5e72011-11-30 01:09:44 +000043
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 Grosbachab5830e2011-12-14 02:16:11 +000048 // Map of register aliases registers via the .req directive.
49 StringMap<unsigned> RegisterReqs;
50
Jim Grosbached16ec42011-08-29 22:24:09 +000051 struct {
52 ARMCC::CondCodes Cond; // Condition for IT block.
53 unsigned Mask:4; // Condition mask for instructions.
54 // Starting at first 1 (from lsb).
55 // '1' condition as indicated in IT.
56 // '0' inverse of condition (else).
57 // Count of instructions in IT block is
58 // 4 - trailingzeroes(mask)
59
60 bool FirstCond; // Explicit flag for when we're parsing the
61 // First instruction in the IT block. It's
62 // implied in the mask, so needs special
63 // handling.
64
65 unsigned CurPosition; // Current position in parsing of IT
66 // block. In range [0,3]. Initialized
67 // according to count of instructions in block.
68 // ~0U if no active IT block.
69 } ITState;
70 bool inITBlock() { return ITState.CurPosition != ~0U;}
Jim Grosbacha0d34d32011-09-02 23:22:08 +000071 void forwardITPosition() {
72 if (!inITBlock()) return;
73 // Move to the next instruction in the IT block, if there is one. If not,
74 // mark the block as done.
75 unsigned TZ = CountTrailingZeros_32(ITState.Mask);
76 if (++ITState.CurPosition == 5 - TZ)
77 ITState.CurPosition = ~0U; // Done with the IT block after this.
78 }
Jim Grosbached16ec42011-08-29 22:24:09 +000079
80
Kevin Enderbyccab3172009-09-15 00:27:25 +000081 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyccab3172009-09-15 00:27:25 +000082 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
83
84 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
Kevin Enderbyccab3172009-09-15 00:27:25 +000085 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
86
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000087 int tryParseRegister();
88 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d6022d2011-07-26 20:41:24 +000089 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000090 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd3595712011-08-03 23:50:40 +000091 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000092 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
93 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbachd3595712011-08-03 23:50:40 +000094 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
95 unsigned &ShiftAmount);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000096 bool parseDirectiveWord(unsigned Size, SMLoc L);
97 bool parseDirectiveThumb(SMLoc L);
Jim Grosbach7f882392011-12-07 18:04:19 +000098 bool parseDirectiveARM(SMLoc L);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000099 bool parseDirectiveThumbFunc(SMLoc L);
100 bool parseDirectiveCode(SMLoc L);
101 bool parseDirectiveSyntax(SMLoc L);
Jim Grosbachab5830e2011-12-14 02:16:11 +0000102 bool parseDirectiveReq(StringRef Name, SMLoc L);
103 bool parseDirectiveUnreq(SMLoc L);
Jason W Kim135d2442011-12-20 17:38:12 +0000104 bool parseDirectiveArch(SMLoc L);
105 bool parseDirectiveEabiAttr(SMLoc L);
Kevin Enderby146dcf22009-10-15 20:48:48 +0000106
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000107 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000108 bool &CarrySetting, unsigned &ProcessorIMod,
109 StringRef &ITMask);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000110 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +0000111 bool &CanAcceptPredicationCode);
Jim Grosbach624bcc72010-10-29 14:46:02 +0000112
Evan Cheng4d1ca962011-07-08 01:53:10 +0000113 bool isThumb() const {
114 // FIXME: Can tablegen auto-generate this?
Evan Cheng91111d22011-07-09 05:47:46 +0000115 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000116 }
Evan Cheng4d1ca962011-07-08 01:53:10 +0000117 bool isThumbOne() const {
Evan Cheng91111d22011-07-09 05:47:46 +0000118 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000119 }
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000120 bool isThumbTwo() const {
121 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
122 }
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000123 bool hasV6Ops() const {
124 return STI.getFeatureBits() & ARM::HasV6Ops;
125 }
James Molloy21efa7d2011-09-28 14:21:38 +0000126 bool hasV7Ops() const {
127 return STI.getFeatureBits() & ARM::HasV7Ops;
128 }
Evan Cheng284b4672011-07-08 22:36:29 +0000129 void SwitchMode() {
Evan Cheng91111d22011-07-09 05:47:46 +0000130 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
131 setAvailableFeatures(FB);
Evan Cheng284b4672011-07-08 22:36:29 +0000132 }
James Molloy21efa7d2011-09-28 14:21:38 +0000133 bool isMClass() const {
134 return STI.getFeatureBits() & ARM::FeatureMClass;
135 }
Evan Cheng4d1ca962011-07-08 01:53:10 +0000136
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000137 /// @name Auto-generated Match Functions
138 /// {
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +0000139
Chris Lattner3e4582a2010-09-06 19:11:01 +0000140#define GET_ASSEMBLER_HEADER
141#include "ARMGenAsmMatcher.inc"
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000142
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000143 /// }
144
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000145 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000146 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbach861e49c2011-02-12 01:34:40 +0000147 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000148 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbach861e49c2011-02-12 01:34:40 +0000149 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach48399582011-10-12 17:34:41 +0000150 OperandMatchResultTy parseCoprocOptionOperand(
151 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000152 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopescdd20af2011-02-18 19:49:06 +0000153 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000154 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopescdd20af2011-02-18 19:49:06 +0000155 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000156 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopescdd20af2011-02-18 19:49:06 +0000157 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach27c1e252011-07-21 17:23:04 +0000158 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
159 StringRef Op, int Low, int High);
160 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
161 return parsePKHImm(O, "lsl", 0, 31);
162 }
163 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
164 return parsePKHImm(O, "asr", 1, 32);
165 }
Jim Grosbach0a547702011-07-22 17:44:50 +0000166 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000167 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach833b9d32011-07-27 20:15:40 +0000168 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach864b6092011-07-28 21:34:26 +0000169 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachd3595712011-08-03 23:50:40 +0000170 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach1d9d5e92011-08-10 21:56:18 +0000171 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbache7fbce72011-10-03 23:38:36 +0000172 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000173 OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach04945c42011-12-02 00:35:16 +0000174 OperandMatchResultTy parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000175
176 // Asm Match Converter Methods
Jim Grosbach7db8d692011-09-08 22:07:06 +0000177 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
178 const SmallVectorImpl<MCParsedAsmOperand*> &);
179 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
180 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachc086f682011-09-08 00:39:19 +0000181 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
182 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach9c0b86a2011-09-16 21:55:56 +0000183 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
184 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000185 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000186 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson16d33f32011-08-26 20:43:14 +0000187 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
188 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd564bf32011-08-11 19:22:40 +0000189 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
190 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000191 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000192 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd886f8c2011-08-11 21:17:22 +0000193 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
194 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd3595712011-08-03 23:50:40 +0000195 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
196 const SmallVectorImpl<MCParsedAsmOperand*> &);
197 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
198 const SmallVectorImpl<MCParsedAsmOperand*> &);
199 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
200 const SmallVectorImpl<MCParsedAsmOperand*> &);
201 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
202 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach5b96b802011-08-10 20:29:19 +0000203 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
204 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheb09f492011-08-11 20:28:23 +0000205 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
206 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachcd4dd252011-08-10 22:42:16 +0000207 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
208 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach8e048492011-08-19 22:07:46 +0000209 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
210 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach3ea06572011-10-24 22:16:58 +0000211 bool cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
212 const SmallVectorImpl<MCParsedAsmOperand*> &);
213 bool cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
214 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach05df4602011-10-31 21:50:31 +0000215 bool cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
216 const SmallVectorImpl<MCParsedAsmOperand*> &);
217 bool cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
218 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000219
220 bool validateInstruction(MCInst &Inst,
221 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachafad0532011-11-10 23:42:14 +0000222 bool processInstruction(MCInst &Inst,
Jim Grosbach8ba76c62011-08-11 17:35:48 +0000223 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach7283da92011-08-16 21:12:37 +0000224 bool shouldOmitCCOutOperand(StringRef Mnemonic,
225 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000226
Kevin Enderbyccab3172009-09-15 00:27:25 +0000227public:
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000228 enum ARMMatchResultTy {
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000229 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbached16ec42011-08-29 22:24:09 +0000230 Match_RequiresNotITBlock,
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000231 Match_RequiresV6,
232 Match_RequiresThumb2
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000233 };
234
Evan Cheng91111d22011-07-09 05:47:46 +0000235 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng11424442011-07-26 00:24:13 +0000236 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Cheng4d1ca962011-07-08 01:53:10 +0000237 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng284b4672011-07-08 22:36:29 +0000238
Evan Cheng4d1ca962011-07-08 01:53:10 +0000239 // Initialize the set of available features.
Evan Cheng91111d22011-07-09 05:47:46 +0000240 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbached16ec42011-08-29 22:24:09 +0000241
242 // Not in an ITBlock to start with.
243 ITState.CurPosition = ~0U;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000244 }
Kevin Enderbyccab3172009-09-15 00:27:25 +0000245
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000246 // Implementation of the MCTargetAsmParser interface:
247 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
248 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000249 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000250 bool ParseDirective(AsmToken DirectiveID);
251
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000252 unsigned checkTargetMatchPredicate(MCInst &Inst);
253
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000254 bool MatchAndEmitInstruction(SMLoc IDLoc,
255 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
256 MCStreamer &Out);
Kevin Enderbyccab3172009-09-15 00:27:25 +0000257};
Jim Grosbach624bcc72010-10-29 14:46:02 +0000258} // end anonymous namespace
259
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +0000260namespace {
261
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000262/// ARMOperand - Instances of this class represent a parsed ARM machine
263/// instruction.
Bill Wendlingee7f1f92010-11-06 21:42:12 +0000264class ARMOperand : public MCParsedAsmOperand {
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000265 enum KindTy {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000266 k_CondCode,
267 k_CCOut,
268 k_ITCondMask,
269 k_CoprocNum,
270 k_CoprocReg,
Jim Grosbach48399582011-10-12 17:34:41 +0000271 k_CoprocOption,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000272 k_Immediate,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000273 k_MemBarrierOpt,
274 k_Memory,
275 k_PostIndexRegister,
276 k_MSRMask,
277 k_ProcIFlags,
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000278 k_VectorIndex,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000279 k_Register,
280 k_RegisterList,
281 k_DPRRegisterList,
282 k_SPRRegisterList,
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000283 k_VectorList,
Jim Grosbachcd6f5e72011-11-30 01:09:44 +0000284 k_VectorListAllLanes,
Jim Grosbach04945c42011-12-02 00:35:16 +0000285 k_VectorListIndexed,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000286 k_ShiftedRegister,
287 k_ShiftedImmediate,
288 k_ShifterImmediate,
289 k_RotateImmediate,
290 k_BitfieldDescriptor,
291 k_Token
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000292 } Kind;
293
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000294 SMLoc StartLoc, EndLoc;
Bill Wendling0ab0f672010-11-18 21:50:54 +0000295 SmallVector<unsigned, 8> Registers;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000296
297 union {
298 struct {
Daniel Dunbard8042b72010-08-11 06:36:53 +0000299 ARMCC::CondCodes Val;
300 } CC;
301
302 struct {
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000303 unsigned Val;
304 } Cop;
305
306 struct {
Jim Grosbach48399582011-10-12 17:34:41 +0000307 unsigned Val;
308 } CoprocOption;
309
310 struct {
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000311 unsigned Mask:4;
312 } ITMask;
313
314 struct {
315 ARM_MB::MemBOpt Val;
316 } MBOpt;
317
318 struct {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000319 ARM_PROC::IFlags Val;
320 } IFlags;
321
322 struct {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000323 unsigned Val;
324 } MMask;
325
326 struct {
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000327 const char *Data;
328 unsigned Length;
329 } Tok;
330
331 struct {
332 unsigned RegNum;
333 } Reg;
334
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000335 // A vector register list is a sequential list of 1 to 4 registers.
336 struct {
337 unsigned RegNum;
338 unsigned Count;
Jim Grosbach04945c42011-12-02 00:35:16 +0000339 unsigned LaneIndex;
Jim Grosbach2f50e922011-12-15 21:44:33 +0000340 bool isDoubleSpaced;
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000341 } VectorList;
342
Bill Wendlingb884a8e2010-11-06 22:19:43 +0000343 struct {
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000344 unsigned Val;
345 } VectorIndex;
346
347 struct {
Kevin Enderbyf5079942009-10-13 22:19:02 +0000348 const MCExpr *Val;
349 } Imm;
Jim Grosbach624bcc72010-10-29 14:46:02 +0000350
Daniel Dunbar2be732a2011-01-10 15:26:21 +0000351 /// Combined record for all forms of ARM address expressions.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000352 struct {
353 unsigned BaseRegNum;
Jim Grosbachd3595712011-08-03 23:50:40 +0000354 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
355 // was specified.
356 const MCConstantExpr *OffsetImm; // Offset immediate value
357 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
358 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbacha95ec992011-10-11 17:29:55 +0000359 unsigned ShiftImm; // shift for OffsetReg.
360 unsigned Alignment; // 0 = no alignment specified
Jim Grosbachcef98cd2011-12-19 18:31:43 +0000361 // n = alignment in bytes (2, 4, 8, 16, or 32)
Jim Grosbachd3595712011-08-03 23:50:40 +0000362 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbach871dff72011-10-11 15:59:20 +0000363 } Memory;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000364
365 struct {
Jim Grosbachd3595712011-08-03 23:50:40 +0000366 unsigned RegNum;
Jim Grosbachc320c852011-08-05 21:28:30 +0000367 bool isAdd;
368 ARM_AM::ShiftOpc ShiftTy;
369 unsigned ShiftImm;
Jim Grosbachd3595712011-08-03 23:50:40 +0000370 } PostIdxReg;
371
372 struct {
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000373 bool isASR;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000374 unsigned Imm;
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000375 } ShifterImm;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000376 struct {
377 ARM_AM::ShiftOpc ShiftTy;
378 unsigned SrcReg;
379 unsigned ShiftReg;
380 unsigned ShiftImm;
Jim Grosbachac798e12011-07-25 20:49:51 +0000381 } RegShiftedReg;
Owen Andersonb595ed02011-07-21 18:54:16 +0000382 struct {
383 ARM_AM::ShiftOpc ShiftTy;
384 unsigned SrcReg;
385 unsigned ShiftImm;
Jim Grosbachac798e12011-07-25 20:49:51 +0000386 } RegShiftedImm;
Jim Grosbach833b9d32011-07-27 20:15:40 +0000387 struct {
388 unsigned Imm;
389 } RotImm;
Jim Grosbach864b6092011-07-28 21:34:26 +0000390 struct {
391 unsigned LSB;
392 unsigned Width;
393 } Bitfield;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000394 };
Jim Grosbach624bcc72010-10-29 14:46:02 +0000395
Bill Wendlingee7f1f92010-11-06 21:42:12 +0000396 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
397public:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000398 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
399 Kind = o.Kind;
400 StartLoc = o.StartLoc;
401 EndLoc = o.EndLoc;
402 switch (Kind) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000403 case k_CondCode:
Daniel Dunbard8042b72010-08-11 06:36:53 +0000404 CC = o.CC;
405 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000406 case k_ITCondMask:
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000407 ITMask = o.ITMask;
408 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000409 case k_Token:
Daniel Dunbard8042b72010-08-11 06:36:53 +0000410 Tok = o.Tok;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000411 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000412 case k_CCOut:
413 case k_Register:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000414 Reg = o.Reg;
415 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000416 case k_RegisterList:
417 case k_DPRRegisterList:
418 case k_SPRRegisterList:
Bill Wendling0ab0f672010-11-18 21:50:54 +0000419 Registers = o.Registers;
Bill Wendling7cef4472010-11-06 19:56:04 +0000420 break;
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000421 case k_VectorList:
Jim Grosbachcd6f5e72011-11-30 01:09:44 +0000422 case k_VectorListAllLanes:
Jim Grosbach04945c42011-12-02 00:35:16 +0000423 case k_VectorListIndexed:
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000424 VectorList = o.VectorList;
425 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000426 case k_CoprocNum:
427 case k_CoprocReg:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000428 Cop = o.Cop;
429 break;
Jim Grosbach48399582011-10-12 17:34:41 +0000430 case k_CoprocOption:
431 CoprocOption = o.CoprocOption;
432 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000433 case k_Immediate:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000434 Imm = o.Imm;
435 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000436 case k_MemBarrierOpt:
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000437 MBOpt = o.MBOpt;
438 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000439 case k_Memory:
Jim Grosbach871dff72011-10-11 15:59:20 +0000440 Memory = o.Memory;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000441 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000442 case k_PostIndexRegister:
Jim Grosbachd3595712011-08-03 23:50:40 +0000443 PostIdxReg = o.PostIdxReg;
444 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000445 case k_MSRMask:
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000446 MMask = o.MMask;
447 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000448 case k_ProcIFlags:
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000449 IFlags = o.IFlags;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000450 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000451 case k_ShifterImmediate:
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000452 ShifterImm = o.ShifterImm;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000453 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000454 case k_ShiftedRegister:
Jim Grosbachac798e12011-07-25 20:49:51 +0000455 RegShiftedReg = o.RegShiftedReg;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000456 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000457 case k_ShiftedImmediate:
Jim Grosbachac798e12011-07-25 20:49:51 +0000458 RegShiftedImm = o.RegShiftedImm;
Owen Andersonb595ed02011-07-21 18:54:16 +0000459 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000460 case k_RotateImmediate:
Jim Grosbach833b9d32011-07-27 20:15:40 +0000461 RotImm = o.RotImm;
462 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000463 case k_BitfieldDescriptor:
Jim Grosbach864b6092011-07-28 21:34:26 +0000464 Bitfield = o.Bitfield;
465 break;
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000466 case k_VectorIndex:
467 VectorIndex = o.VectorIndex;
468 break;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000469 }
470 }
Jim Grosbach624bcc72010-10-29 14:46:02 +0000471
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000472 /// getStartLoc - Get the location of the first token of this operand.
473 SMLoc getStartLoc() const { return StartLoc; }
474 /// getEndLoc - Get the location of the last token of this operand.
475 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000476
Daniel Dunbard8042b72010-08-11 06:36:53 +0000477 ARMCC::CondCodes getCondCode() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000478 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbard8042b72010-08-11 06:36:53 +0000479 return CC.Val;
480 }
481
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000482 unsigned getCoproc() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000483 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000484 return Cop.Val;
485 }
486
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000487 StringRef getToken() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000488 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000489 return StringRef(Tok.Data, Tok.Length);
490 }
491
492 unsigned getReg() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000493 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling2cae3272010-11-09 22:44:22 +0000494 return Reg.RegNum;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000495 }
496
Bill Wendlingbed94652010-11-09 23:28:44 +0000497 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000498 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
499 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling0ab0f672010-11-18 21:50:54 +0000500 return Registers;
Bill Wendling7cef4472010-11-06 19:56:04 +0000501 }
502
Kevin Enderbyf5079942009-10-13 22:19:02 +0000503 const MCExpr *getImm() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000504 assert(isImm() && "Invalid access!");
Kevin Enderbyf5079942009-10-13 22:19:02 +0000505 return Imm.Val;
506 }
507
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000508 unsigned getVectorIndex() const {
509 assert(Kind == k_VectorIndex && "Invalid access!");
510 return VectorIndex.Val;
511 }
512
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000513 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000514 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000515 return MBOpt.Val;
516 }
517
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000518 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000519 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000520 return IFlags.Val;
521 }
522
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000523 unsigned getMSRMask() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000524 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000525 return MMask.Val;
526 }
527
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000528 bool isCoprocNum() const { return Kind == k_CoprocNum; }
529 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach48399582011-10-12 17:34:41 +0000530 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000531 bool isCondCode() const { return Kind == k_CondCode; }
532 bool isCCOut() const { return Kind == k_CCOut; }
533 bool isITMask() const { return Kind == k_ITCondMask; }
534 bool isITCondCode() const { return Kind == k_CondCode; }
535 bool isImm() const { return Kind == k_Immediate; }
Jim Grosbacha9d36fb2012-01-20 18:09:51 +0000536 bool isFPImm() const {
537 if (!isImm()) return false;
538 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
539 if (!CE) return false;
540 int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
541 return Val != -1;
542 }
Jim Grosbachea231912011-12-22 22:19:05 +0000543 bool isFBits16() const {
544 if (!isImm()) return false;
545 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
546 if (!CE) return false;
547 int64_t Value = CE->getValue();
548 return Value >= 0 && Value <= 16;
549 }
550 bool isFBits32() const {
551 if (!isImm()) return false;
552 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
553 if (!CE) return false;
554 int64_t Value = CE->getValue();
555 return Value >= 1 && Value <= 32;
556 }
Jim Grosbach7db8d692011-09-08 22:07:06 +0000557 bool isImm8s4() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000558 if (!isImm()) return false;
Jim Grosbach7db8d692011-09-08 22:07:06 +0000559 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
560 if (!CE) return false;
561 int64_t Value = CE->getValue();
562 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
563 }
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000564 bool isImm0_1020s4() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000565 if (!isImm()) return false;
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000566 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
567 if (!CE) return false;
568 int64_t Value = CE->getValue();
569 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
570 }
571 bool isImm0_508s4() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000572 if (!isImm()) return false;
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000573 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
574 if (!CE) return false;
575 int64_t Value = CE->getValue();
576 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
577 }
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000578 bool isImm0_255() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000579 if (!isImm()) return false;
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000580 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
581 if (!CE) return false;
582 int64_t Value = CE->getValue();
583 return Value >= 0 && Value < 256;
584 }
Jim Grosbach9dff9f42011-12-02 23:34:39 +0000585 bool isImm0_1() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000586 if (!isImm()) return false;
Jim Grosbach9dff9f42011-12-02 23:34:39 +0000587 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
588 if (!CE) return false;
589 int64_t Value = CE->getValue();
590 return Value >= 0 && Value < 2;
591 }
592 bool isImm0_3() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000593 if (!isImm()) return false;
Jim Grosbach9dff9f42011-12-02 23:34:39 +0000594 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
595 if (!CE) return false;
596 int64_t Value = CE->getValue();
597 return Value >= 0 && Value < 4;
598 }
Jim Grosbach31756c22011-07-13 22:01:08 +0000599 bool isImm0_7() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000600 if (!isImm()) return false;
Jim Grosbach31756c22011-07-13 22:01:08 +0000601 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
602 if (!CE) return false;
603 int64_t Value = CE->getValue();
604 return Value >= 0 && Value < 8;
605 }
606 bool isImm0_15() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000607 if (!isImm()) return false;
Jim Grosbach31756c22011-07-13 22:01:08 +0000608 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
609 if (!CE) return false;
610 int64_t Value = CE->getValue();
611 return Value >= 0 && Value < 16;
612 }
Jim Grosbach72e7c4f2011-07-21 23:26:25 +0000613 bool isImm0_31() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000614 if (!isImm()) return false;
Jim Grosbach72e7c4f2011-07-21 23:26:25 +0000615 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
616 if (!CE) return false;
617 int64_t Value = CE->getValue();
618 return Value >= 0 && Value < 32;
619 }
Jim Grosbach00326402011-12-08 01:30:04 +0000620 bool isImm0_63() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000621 if (!isImm()) return false;
Jim Grosbach00326402011-12-08 01:30:04 +0000622 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
623 if (!CE) return false;
624 int64_t Value = CE->getValue();
625 return Value >= 0 && Value < 64;
626 }
Jim Grosbachd4b82492011-12-07 01:07:24 +0000627 bool isImm8() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000628 if (!isImm()) return false;
Jim Grosbachd4b82492011-12-07 01:07:24 +0000629 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
630 if (!CE) return false;
631 int64_t Value = CE->getValue();
632 return Value == 8;
633 }
634 bool isImm16() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000635 if (!isImm()) return false;
Jim Grosbachd4b82492011-12-07 01:07:24 +0000636 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
637 if (!CE) return false;
638 int64_t Value = CE->getValue();
639 return Value == 16;
640 }
641 bool isImm32() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000642 if (!isImm()) return false;
Jim Grosbachd4b82492011-12-07 01:07:24 +0000643 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
644 if (!CE) return false;
645 int64_t Value = CE->getValue();
646 return Value == 32;
647 }
Jim Grosbachba7d6ed2011-12-08 22:06:06 +0000648 bool isShrImm8() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000649 if (!isImm()) return false;
Jim Grosbachba7d6ed2011-12-08 22:06:06 +0000650 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
651 if (!CE) return false;
652 int64_t Value = CE->getValue();
653 return Value > 0 && Value <= 8;
654 }
655 bool isShrImm16() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000656 if (!isImm()) return false;
Jim Grosbachba7d6ed2011-12-08 22:06:06 +0000657 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
658 if (!CE) return false;
659 int64_t Value = CE->getValue();
660 return Value > 0 && Value <= 16;
661 }
662 bool isShrImm32() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000663 if (!isImm()) return false;
Jim Grosbachba7d6ed2011-12-08 22:06:06 +0000664 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
665 if (!CE) return false;
666 int64_t Value = CE->getValue();
667 return Value > 0 && Value <= 32;
668 }
669 bool isShrImm64() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000670 if (!isImm()) return false;
Jim Grosbachba7d6ed2011-12-08 22:06:06 +0000671 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
672 if (!CE) return false;
673 int64_t Value = CE->getValue();
674 return Value > 0 && Value <= 64;
675 }
Jim Grosbachd4b82492011-12-07 01:07:24 +0000676 bool isImm1_7() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000677 if (!isImm()) return false;
Jim Grosbachd4b82492011-12-07 01:07:24 +0000678 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
679 if (!CE) return false;
680 int64_t Value = CE->getValue();
681 return Value > 0 && Value < 8;
682 }
683 bool isImm1_15() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000684 if (!isImm()) return false;
Jim Grosbachd4b82492011-12-07 01:07:24 +0000685 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
686 if (!CE) return false;
687 int64_t Value = CE->getValue();
688 return Value > 0 && Value < 16;
689 }
690 bool isImm1_31() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000691 if (!isImm()) return false;
Jim Grosbachd4b82492011-12-07 01:07:24 +0000692 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
693 if (!CE) return false;
694 int64_t Value = CE->getValue();
695 return Value > 0 && Value < 32;
696 }
Jim Grosbach475c6db2011-07-25 23:09:14 +0000697 bool isImm1_16() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000698 if (!isImm()) return false;
Jim Grosbach475c6db2011-07-25 23:09:14 +0000699 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
700 if (!CE) return false;
701 int64_t Value = CE->getValue();
702 return Value > 0 && Value < 17;
703 }
Jim Grosbach801e0a32011-07-22 23:16:18 +0000704 bool isImm1_32() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000705 if (!isImm()) return false;
Jim Grosbach801e0a32011-07-22 23:16:18 +0000706 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
707 if (!CE) return false;
708 int64_t Value = CE->getValue();
709 return Value > 0 && Value < 33;
710 }
Jim Grosbachc14871c2011-11-10 19:18:01 +0000711 bool isImm0_32() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000712 if (!isImm()) return false;
Jim Grosbachc14871c2011-11-10 19:18:01 +0000713 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
714 if (!CE) return false;
715 int64_t Value = CE->getValue();
716 return Value >= 0 && Value < 33;
717 }
Jim Grosbach975b6412011-07-13 20:10:10 +0000718 bool isImm0_65535() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000719 if (!isImm()) return false;
Jim Grosbach975b6412011-07-13 20:10:10 +0000720 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
721 if (!CE) return false;
722 int64_t Value = CE->getValue();
723 return Value >= 0 && Value < 65536;
724 }
Jim Grosbach7c09e3c2011-07-19 19:13:28 +0000725 bool isImm0_65535Expr() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000726 if (!isImm()) return false;
Jim Grosbach7c09e3c2011-07-19 19:13:28 +0000727 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
728 // If it's not a constant expression, it'll generate a fixup and be
729 // handled later.
730 if (!CE) return true;
731 int64_t Value = CE->getValue();
732 return Value >= 0 && Value < 65536;
733 }
Jim Grosbachf1637842011-07-26 16:24:27 +0000734 bool isImm24bit() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000735 if (!isImm()) return false;
Jim Grosbachf1637842011-07-26 16:24:27 +0000736 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
737 if (!CE) return false;
738 int64_t Value = CE->getValue();
739 return Value >= 0 && Value <= 0xffffff;
740 }
Jim Grosbach46dd4132011-08-17 21:51:27 +0000741 bool isImmThumbSR() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000742 if (!isImm()) return false;
Jim Grosbach46dd4132011-08-17 21:51:27 +0000743 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
744 if (!CE) return false;
745 int64_t Value = CE->getValue();
746 return Value > 0 && Value < 33;
747 }
Jim Grosbach27c1e252011-07-21 17:23:04 +0000748 bool isPKHLSLImm() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000749 if (!isImm()) return false;
Jim Grosbach27c1e252011-07-21 17:23:04 +0000750 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
751 if (!CE) return false;
752 int64_t Value = CE->getValue();
753 return Value >= 0 && Value < 32;
754 }
755 bool isPKHASRImm() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000756 if (!isImm()) return false;
Jim Grosbach27c1e252011-07-21 17:23:04 +0000757 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
758 if (!CE) return false;
759 int64_t Value = CE->getValue();
760 return Value > 0 && Value <= 32;
761 }
Jim Grosbach9720dcf2011-07-19 16:50:30 +0000762 bool isARMSOImm() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000763 if (!isImm()) return false;
Jim Grosbach9720dcf2011-07-19 16:50:30 +0000764 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
765 if (!CE) return false;
766 int64_t Value = CE->getValue();
767 return ARM_AM::getSOImmVal(Value) != -1;
768 }
Jim Grosbach3d785ed2011-10-28 22:50:54 +0000769 bool isARMSOImmNot() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000770 if (!isImm()) return false;
Jim Grosbach3d785ed2011-10-28 22:50:54 +0000771 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
772 if (!CE) return false;
773 int64_t Value = CE->getValue();
774 return ARM_AM::getSOImmVal(~Value) != -1;
775 }
Jim Grosbach30506252011-12-08 00:31:07 +0000776 bool isARMSOImmNeg() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000777 if (!isImm()) return false;
Jim Grosbach30506252011-12-08 00:31:07 +0000778 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
779 if (!CE) return false;
780 int64_t Value = CE->getValue();
781 return ARM_AM::getSOImmVal(-Value) != -1;
782 }
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000783 bool isT2SOImm() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000784 if (!isImm()) return false;
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000785 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
786 if (!CE) return false;
787 int64_t Value = CE->getValue();
788 return ARM_AM::getT2SOImmVal(Value) != -1;
789 }
Jim Grosbachb009a872011-10-28 22:36:30 +0000790 bool isT2SOImmNot() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000791 if (!isImm()) return false;
Jim Grosbachb009a872011-10-28 22:36:30 +0000792 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
793 if (!CE) return false;
794 int64_t Value = CE->getValue();
795 return ARM_AM::getT2SOImmVal(~Value) != -1;
796 }
Jim Grosbach30506252011-12-08 00:31:07 +0000797 bool isT2SOImmNeg() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000798 if (!isImm()) return false;
Jim Grosbach30506252011-12-08 00:31:07 +0000799 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
800 if (!CE) return false;
801 int64_t Value = CE->getValue();
802 return ARM_AM::getT2SOImmVal(-Value) != -1;
803 }
Jim Grosbach0a547702011-07-22 17:44:50 +0000804 bool isSetEndImm() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000805 if (!isImm()) return false;
Jim Grosbach0a547702011-07-22 17:44:50 +0000806 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
807 if (!CE) return false;
808 int64_t Value = CE->getValue();
809 return Value == 1 || Value == 0;
810 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000811 bool isReg() const { return Kind == k_Register; }
812 bool isRegList() const { return Kind == k_RegisterList; }
813 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
814 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
815 bool isToken() const { return Kind == k_Token; }
816 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
817 bool isMemory() const { return Kind == k_Memory; }
818 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
819 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
820 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
821 bool isRotImm() const { return Kind == k_RotateImmediate; }
822 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
823 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachc320c852011-08-05 21:28:30 +0000824 bool isPostIdxReg() const {
Jim Grosbachee201fa2011-11-14 17:52:47 +0000825 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachc320c852011-08-05 21:28:30 +0000826 }
Jim Grosbacha95ec992011-10-11 17:29:55 +0000827 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachc11b7c32011-10-10 23:06:42 +0000828 if (!isMemory())
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000829 return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000830 // No offset of any kind.
Jim Grosbacha95ec992011-10-11 17:29:55 +0000831 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
832 (alignOK || Memory.Alignment == 0);
833 }
Jim Grosbach94298a92012-01-18 22:46:46 +0000834 bool isMemPCRelImm12() const {
835 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
836 return false;
837 // Base register must be PC.
838 if (Memory.BaseRegNum != ARM::PC)
839 return false;
840 // Immediate offset in range [-4095, 4095].
841 if (!Memory.OffsetImm) return true;
842 int64_t Val = Memory.OffsetImm->getValue();
843 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
844 }
Jim Grosbacha95ec992011-10-11 17:29:55 +0000845 bool isAlignedMemory() const {
846 return isMemNoOffset(true);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000847 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000848 bool isAddrMode2() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000849 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000850 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000851 if (Memory.OffsetRegNum) return true;
Jim Grosbachd3595712011-08-03 23:50:40 +0000852 // Immediate offset in range [-4095, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +0000853 if (!Memory.OffsetImm) return true;
854 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachd3595712011-08-03 23:50:40 +0000855 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +0000856 }
Jim Grosbachcd17c122011-08-04 23:01:30 +0000857 bool isAM2OffsetImm() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000858 if (!isImm()) return false;
Jim Grosbachcd17c122011-08-04 23:01:30 +0000859 // Immediate offset in range [-4095, 4095].
860 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
861 if (!CE) return false;
862 int64_t Val = CE->getValue();
863 return Val > -4096 && Val < 4096;
864 }
Jim Grosbach5b96b802011-08-10 20:29:19 +0000865 bool isAddrMode3() const {
Jim Grosbach8648c102011-12-19 23:06:24 +0000866 // If we have an immediate that's not a constant, treat it as a label
867 // reference needing a fixup. If it is a constant, it's something else
868 // and we reject it.
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000869 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach8648c102011-12-19 23:06:24 +0000870 return true;
Jim Grosbacha95ec992011-10-11 17:29:55 +0000871 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000872 // No shifts are legal for AM3.
Jim Grosbach871dff72011-10-11 15:59:20 +0000873 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000874 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000875 if (Memory.OffsetRegNum) return true;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000876 // Immediate offset in range [-255, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +0000877 if (!Memory.OffsetImm) return true;
878 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach5b96b802011-08-10 20:29:19 +0000879 return Val > -256 && Val < 256;
880 }
881 bool isAM3Offset() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000882 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach5b96b802011-08-10 20:29:19 +0000883 return false;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000884 if (Kind == k_PostIndexRegister)
Jim Grosbach5b96b802011-08-10 20:29:19 +0000885 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
886 // Immediate offset in range [-255, 255].
887 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
888 if (!CE) return false;
889 int64_t Val = CE->getValue();
Jim Grosbach1d9d5e92011-08-10 21:56:18 +0000890 // Special case, #-0 is INT32_MIN.
891 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000892 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000893 bool isAddrMode5() const {
Jim Grosbachfb2f1d62011-11-01 01:24:45 +0000894 // If we have an immediate that's not a constant, treat it as a label
895 // reference needing a fixup. If it is a constant, it's something else
896 // and we reject it.
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000897 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbachfb2f1d62011-11-01 01:24:45 +0000898 return true;
Jim Grosbacha95ec992011-10-11 17:29:55 +0000899 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000900 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000901 if (Memory.OffsetRegNum) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000902 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbach871dff72011-10-11 15:59:20 +0000903 if (!Memory.OffsetImm) return true;
904 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson967674d2011-08-29 19:36:44 +0000905 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbachfb2f1d62011-11-01 01:24:45 +0000906 Val == INT32_MIN;
Bill Wendling8d2aa032010-11-08 23:49:57 +0000907 }
Jim Grosbach05541f42011-09-19 22:21:13 +0000908 bool isMemTBB() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000909 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000910 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach05541f42011-09-19 22:21:13 +0000911 return false;
912 return true;
913 }
914 bool isMemTBH() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000915 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000916 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
917 Memory.Alignment != 0 )
Jim Grosbach05541f42011-09-19 22:21:13 +0000918 return false;
919 return true;
920 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000921 bool isMemRegOffset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000922 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendling092a7bd2010-12-14 03:36:38 +0000923 return false;
Daniel Dunbar7ed45592011-01-18 05:34:11 +0000924 return true;
Bill Wendling092a7bd2010-12-14 03:36:38 +0000925 }
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000926 bool isT2MemRegOffset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000927 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
928 Memory.Alignment != 0)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000929 return false;
930 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbach871dff72011-10-11 15:59:20 +0000931 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000932 return true;
Jim Grosbach871dff72011-10-11 15:59:20 +0000933 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000934 return false;
935 return true;
936 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000937 bool isMemThumbRR() const {
938 // Thumb reg+reg addressing is simple. Just two registers, a base and
939 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbach871dff72011-10-11 15:59:20 +0000940 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000941 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendling811c9362010-11-30 07:44:32 +0000942 return false;
Jim Grosbach871dff72011-10-11 15:59:20 +0000943 return isARMLowRegister(Memory.BaseRegNum) &&
944 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach3fe94e32011-08-19 17:55:24 +0000945 }
946 bool isMemThumbRIs4() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000947 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000948 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach3fe94e32011-08-19 17:55:24 +0000949 return false;
950 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbach871dff72011-10-11 15:59:20 +0000951 if (!Memory.OffsetImm) return true;
952 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach23983d62011-08-19 18:13:48 +0000953 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
954 }
Jim Grosbach26d35872011-08-19 18:55:51 +0000955 bool isMemThumbRIs2() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000956 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000957 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach26d35872011-08-19 18:55:51 +0000958 return false;
959 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbach871dff72011-10-11 15:59:20 +0000960 if (!Memory.OffsetImm) return true;
961 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach26d35872011-08-19 18:55:51 +0000962 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
963 }
Jim Grosbacha32c7532011-08-19 18:49:59 +0000964 bool isMemThumbRIs1() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000965 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000966 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbacha32c7532011-08-19 18:49:59 +0000967 return false;
968 // Immediate offset in range [0, 31].
Jim Grosbach871dff72011-10-11 15:59:20 +0000969 if (!Memory.OffsetImm) return true;
970 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha32c7532011-08-19 18:49:59 +0000971 return Val >= 0 && Val <= 31;
972 }
Jim Grosbach23983d62011-08-19 18:13:48 +0000973 bool isMemThumbSPI() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000974 if (!isMemory() || Memory.OffsetRegNum != 0 ||
975 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbach23983d62011-08-19 18:13:48 +0000976 return false;
977 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +0000978 if (!Memory.OffsetImm) return true;
979 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach23983d62011-08-19 18:13:48 +0000980 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendling811c9362010-11-30 07:44:32 +0000981 }
Jim Grosbach7db8d692011-09-08 22:07:06 +0000982 bool isMemImm8s4Offset() const {
Jim Grosbach8648c102011-12-19 23:06:24 +0000983 // If we have an immediate that's not a constant, treat it as a label
984 // reference needing a fixup. If it is a constant, it's something else
985 // and we reject it.
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000986 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach8648c102011-12-19 23:06:24 +0000987 return true;
Jim Grosbacha95ec992011-10-11 17:29:55 +0000988 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7db8d692011-09-08 22:07:06 +0000989 return false;
990 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +0000991 if (!Memory.OffsetImm) return true;
992 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7db8d692011-09-08 22:07:06 +0000993 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
994 }
Jim Grosbacha05627e2011-09-09 18:37:27 +0000995 bool isMemImm0_1020s4Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000996 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha05627e2011-09-09 18:37:27 +0000997 return false;
998 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +0000999 if (!Memory.OffsetImm) return true;
1000 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha05627e2011-09-09 18:37:27 +00001001 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
1002 }
Jim Grosbachd3595712011-08-03 23:50:40 +00001003 bool isMemImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001004 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachd3595712011-08-03 23:50:40 +00001005 return false;
Jim Grosbach94298a92012-01-18 22:46:46 +00001006 // Base reg of PC isn't allowed for these encodings.
1007 if (Memory.BaseRegNum == ARM::PC) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +00001008 // Immediate offset in range [-255, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +00001009 if (!Memory.OffsetImm) return true;
1010 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson49168402011-09-23 22:25:02 +00001011 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbachd3595712011-08-03 23:50:40 +00001012 }
Jim Grosbach2392c532011-09-07 23:39:14 +00001013 bool isMemPosImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001014 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach2392c532011-09-07 23:39:14 +00001015 return false;
1016 // Immediate offset in range [0, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +00001017 if (!Memory.OffsetImm) return true;
1018 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2392c532011-09-07 23:39:14 +00001019 return Val >= 0 && Val < 256;
1020 }
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001021 bool isMemNegImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001022 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001023 return false;
Jim Grosbach94298a92012-01-18 22:46:46 +00001024 // Base reg of PC isn't allowed for these encodings.
1025 if (Memory.BaseRegNum == ARM::PC) return false;
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001026 // Immediate offset in range [-255, -1].
Jim Grosbach175c7d02011-12-06 04:49:29 +00001027 if (!Memory.OffsetImm) return false;
Jim Grosbach871dff72011-10-11 15:59:20 +00001028 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach175c7d02011-12-06 04:49:29 +00001029 return (Val == INT32_MIN) || (Val > -256 && Val < 0);
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001030 }
1031 bool isMemUImm12Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001032 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001033 return false;
1034 // Immediate offset in range [0, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +00001035 if (!Memory.OffsetImm) return true;
1036 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001037 return (Val >= 0 && Val < 4096);
1038 }
Jim Grosbachd3595712011-08-03 23:50:40 +00001039 bool isMemImm12Offset() const {
Jim Grosbach95466ce2011-08-08 20:59:31 +00001040 // If we have an immediate that's not a constant, treat it as a label
1041 // reference needing a fixup. If it is a constant, it's something else
1042 // and we reject it.
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001043 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach95466ce2011-08-08 20:59:31 +00001044 return true;
1045
Jim Grosbacha95ec992011-10-11 17:29:55 +00001046 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachd3595712011-08-03 23:50:40 +00001047 return false;
1048 // Immediate offset in range [-4095, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +00001049 if (!Memory.OffsetImm) return true;
1050 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson967674d2011-08-29 19:36:44 +00001051 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbachd3595712011-08-03 23:50:40 +00001052 }
1053 bool isPostIdxImm8() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001054 if (!isImm()) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +00001055 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1056 if (!CE) return false;
1057 int64_t Val = CE->getValue();
Owen Andersonf02d98d2011-08-29 17:17:09 +00001058 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbachd3595712011-08-03 23:50:40 +00001059 }
Jim Grosbach93981412011-10-11 21:55:36 +00001060 bool isPostIdxImm8s4() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001061 if (!isImm()) return false;
Jim Grosbach93981412011-10-11 21:55:36 +00001062 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1063 if (!CE) return false;
1064 int64_t Val = CE->getValue();
1065 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1066 (Val == INT32_MIN);
1067 }
Jim Grosbachd3595712011-08-03 23:50:40 +00001068
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001069 bool isMSRMask() const { return Kind == k_MSRMask; }
1070 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001071
Jim Grosbach741cd732011-10-17 22:26:03 +00001072 // NEON operands.
Jim Grosbach2f50e922011-12-15 21:44:33 +00001073 bool isSingleSpacedVectorList() const {
1074 return Kind == k_VectorList && !VectorList.isDoubleSpaced;
1075 }
1076 bool isDoubleSpacedVectorList() const {
1077 return Kind == k_VectorList && VectorList.isDoubleSpaced;
1078 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001079 bool isVecListOneD() const {
Jim Grosbach2f50e922011-12-15 21:44:33 +00001080 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001081 return VectorList.Count == 1;
1082 }
1083
Jim Grosbach2f2e3c42011-10-21 18:54:25 +00001084 bool isVecListTwoD() const {
Jim Grosbach2f50e922011-12-15 21:44:33 +00001085 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach2f2e3c42011-10-21 18:54:25 +00001086 return VectorList.Count == 2;
1087 }
1088
Jim Grosbachc4360fe2011-10-21 20:02:19 +00001089 bool isVecListThreeD() const {
Jim Grosbach2f50e922011-12-15 21:44:33 +00001090 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachc4360fe2011-10-21 20:02:19 +00001091 return VectorList.Count == 3;
1092 }
1093
Jim Grosbach846bcff2011-10-21 20:35:01 +00001094 bool isVecListFourD() const {
Jim Grosbach2f50e922011-12-15 21:44:33 +00001095 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach846bcff2011-10-21 20:35:01 +00001096 return VectorList.Count == 4;
1097 }
1098
Jim Grosbach118b38c2011-10-21 22:21:10 +00001099 bool isVecListTwoQ() const {
Jim Grosbach2f50e922011-12-15 21:44:33 +00001100 if (!isDoubleSpacedVectorList()) return false;
1101 return VectorList.Count == 2;
Jim Grosbach118b38c2011-10-21 22:21:10 +00001102 }
1103
Jim Grosbachc5af54e2011-12-21 00:38:54 +00001104 bool isSingleSpacedVectorAllLanes() const {
1105 return Kind == k_VectorListAllLanes && !VectorList.isDoubleSpaced;
1106 }
1107 bool isDoubleSpacedVectorAllLanes() const {
1108 return Kind == k_VectorListAllLanes && VectorList.isDoubleSpaced;
1109 }
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00001110 bool isVecListOneDAllLanes() const {
Jim Grosbachc5af54e2011-12-21 00:38:54 +00001111 if (!isSingleSpacedVectorAllLanes()) return false;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00001112 return VectorList.Count == 1;
1113 }
1114
Jim Grosbach3ecf9762011-11-30 18:21:25 +00001115 bool isVecListTwoDAllLanes() const {
Jim Grosbachc5af54e2011-12-21 00:38:54 +00001116 if (!isSingleSpacedVectorAllLanes()) return false;
1117 return VectorList.Count == 2;
1118 }
1119
1120 bool isVecListTwoQAllLanes() const {
1121 if (!isDoubleSpacedVectorAllLanes()) return false;
Jim Grosbach3ecf9762011-11-30 18:21:25 +00001122 return VectorList.Count == 2;
1123 }
1124
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001125 bool isSingleSpacedVectorIndexed() const {
1126 return Kind == k_VectorListIndexed && !VectorList.isDoubleSpaced;
1127 }
1128 bool isDoubleSpacedVectorIndexed() const {
1129 return Kind == k_VectorListIndexed && VectorList.isDoubleSpaced;
1130 }
Jim Grosbach04945c42011-12-02 00:35:16 +00001131 bool isVecListOneDByteIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001132 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach04945c42011-12-02 00:35:16 +00001133 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1134 }
1135
Jim Grosbachda511042011-12-14 23:35:06 +00001136 bool isVecListOneDHWordIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001137 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbachda511042011-12-14 23:35:06 +00001138 return VectorList.Count == 1 && VectorList.LaneIndex <= 3;
1139 }
1140
1141 bool isVecListOneDWordIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001142 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbachda511042011-12-14 23:35:06 +00001143 return VectorList.Count == 1 && VectorList.LaneIndex <= 1;
1144 }
1145
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00001146 bool isVecListTwoDByteIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001147 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00001148 return VectorList.Count == 2 && VectorList.LaneIndex <= 7;
1149 }
1150
Jim Grosbachda511042011-12-14 23:35:06 +00001151 bool isVecListTwoDHWordIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001152 if (!isSingleSpacedVectorIndexed()) return false;
1153 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1154 }
1155
1156 bool isVecListTwoQWordIndexed() const {
1157 if (!isDoubleSpacedVectorIndexed()) return false;
1158 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1159 }
1160
1161 bool isVecListTwoQHWordIndexed() const {
1162 if (!isDoubleSpacedVectorIndexed()) return false;
Jim Grosbachda511042011-12-14 23:35:06 +00001163 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1164 }
1165
1166 bool isVecListTwoDWordIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001167 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbachda511042011-12-14 23:35:06 +00001168 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1169 }
1170
Jim Grosbacha8b444b2012-01-23 21:53:26 +00001171 bool isVecListThreeDByteIndexed() const {
1172 if (!isSingleSpacedVectorIndexed()) return false;
1173 return VectorList.Count == 3 && VectorList.LaneIndex <= 7;
1174 }
1175
1176 bool isVecListThreeDHWordIndexed() const {
1177 if (!isSingleSpacedVectorIndexed()) return false;
1178 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1179 }
1180
1181 bool isVecListThreeQWordIndexed() const {
1182 if (!isDoubleSpacedVectorIndexed()) return false;
1183 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1184 }
1185
1186 bool isVecListThreeQHWordIndexed() const {
1187 if (!isDoubleSpacedVectorIndexed()) return false;
1188 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1189 }
1190
1191 bool isVecListThreeDWordIndexed() const {
1192 if (!isSingleSpacedVectorIndexed()) return false;
1193 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1194 }
1195
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001196 bool isVectorIndex8() const {
1197 if (Kind != k_VectorIndex) return false;
1198 return VectorIndex.Val < 8;
1199 }
1200 bool isVectorIndex16() const {
1201 if (Kind != k_VectorIndex) return false;
1202 return VectorIndex.Val < 4;
1203 }
1204 bool isVectorIndex32() const {
1205 if (Kind != k_VectorIndex) return false;
1206 return VectorIndex.Val < 2;
1207 }
1208
Jim Grosbach741cd732011-10-17 22:26:03 +00001209 bool isNEONi8splat() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001210 if (!isImm()) return false;
Jim Grosbach741cd732011-10-17 22:26:03 +00001211 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1212 // Must be a constant.
1213 if (!CE) return false;
1214 int64_t Value = CE->getValue();
1215 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1216 // value.
Jim Grosbach741cd732011-10-17 22:26:03 +00001217 return Value >= 0 && Value < 256;
1218 }
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001219
Jim Grosbachcda32ae2011-10-17 23:09:09 +00001220 bool isNEONi16splat() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001221 if (!isImm()) return false;
Jim Grosbachcda32ae2011-10-17 23:09:09 +00001222 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1223 // Must be a constant.
1224 if (!CE) return false;
1225 int64_t Value = CE->getValue();
1226 // i16 value in the range [0,255] or [0x0100, 0xff00]
1227 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1228 }
1229
Jim Grosbach8211c052011-10-18 00:22:00 +00001230 bool isNEONi32splat() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001231 if (!isImm()) return false;
Jim Grosbach8211c052011-10-18 00:22:00 +00001232 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1233 // Must be a constant.
1234 if (!CE) return false;
1235 int64_t Value = CE->getValue();
1236 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1237 return (Value >= 0 && Value < 256) ||
1238 (Value >= 0x0100 && Value <= 0xff00) ||
1239 (Value >= 0x010000 && Value <= 0xff0000) ||
1240 (Value >= 0x01000000 && Value <= 0xff000000);
1241 }
1242
1243 bool isNEONi32vmov() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001244 if (!isImm()) return false;
Jim Grosbach8211c052011-10-18 00:22:00 +00001245 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1246 // Must be a constant.
1247 if (!CE) return false;
1248 int64_t Value = CE->getValue();
1249 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1250 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1251 return (Value >= 0 && Value < 256) ||
1252 (Value >= 0x0100 && Value <= 0xff00) ||
1253 (Value >= 0x010000 && Value <= 0xff0000) ||
1254 (Value >= 0x01000000 && Value <= 0xff000000) ||
1255 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1256 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1257 }
Jim Grosbach045b6c72011-12-19 23:51:07 +00001258 bool isNEONi32vmovNeg() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001259 if (!isImm()) return false;
Jim Grosbach045b6c72011-12-19 23:51:07 +00001260 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1261 // Must be a constant.
1262 if (!CE) return false;
1263 int64_t Value = ~CE->getValue();
1264 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1265 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1266 return (Value >= 0 && Value < 256) ||
1267 (Value >= 0x0100 && Value <= 0xff00) ||
1268 (Value >= 0x010000 && Value <= 0xff0000) ||
1269 (Value >= 0x01000000 && Value <= 0xff000000) ||
1270 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1271 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1272 }
Jim Grosbach8211c052011-10-18 00:22:00 +00001273
Jim Grosbache4454e02011-10-18 16:18:11 +00001274 bool isNEONi64splat() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001275 if (!isImm()) return false;
Jim Grosbache4454e02011-10-18 16:18:11 +00001276 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1277 // Must be a constant.
1278 if (!CE) return false;
1279 uint64_t Value = CE->getValue();
1280 // i64 value with each byte being either 0 or 0xff.
1281 for (unsigned i = 0; i < 8; ++i)
1282 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1283 return true;
1284 }
1285
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001286 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner5d6f6a02010-10-29 00:27:31 +00001287 // Add as immediates when possible. Null MCExpr = 0.
1288 if (Expr == 0)
1289 Inst.addOperand(MCOperand::CreateImm(0));
1290 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001291 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1292 else
1293 Inst.addOperand(MCOperand::CreateExpr(Expr));
1294 }
1295
Daniel Dunbard8042b72010-08-11 06:36:53 +00001296 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001297 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbard8042b72010-08-11 06:36:53 +00001298 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach968c9272010-12-06 18:30:57 +00001299 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1300 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbard8042b72010-08-11 06:36:53 +00001301 }
1302
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001303 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1304 assert(N == 1 && "Invalid number of operands!");
1305 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1306 }
1307
Jim Grosbach48399582011-10-12 17:34:41 +00001308 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1309 assert(N == 1 && "Invalid number of operands!");
1310 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1311 }
1312
1313 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1314 assert(N == 1 && "Invalid number of operands!");
1315 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1316 }
1317
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001318 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1319 assert(N == 1 && "Invalid number of operands!");
1320 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1321 }
1322
1323 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1324 assert(N == 1 && "Invalid number of operands!");
1325 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1326 }
1327
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001328 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1329 assert(N == 1 && "Invalid number of operands!");
1330 Inst.addOperand(MCOperand::CreateReg(getReg()));
1331 }
1332
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001333 void addRegOperands(MCInst &Inst, unsigned N) const {
1334 assert(N == 1 && "Invalid number of operands!");
1335 Inst.addOperand(MCOperand::CreateReg(getReg()));
1336 }
1337
Jim Grosbachac798e12011-07-25 20:49:51 +00001338 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001339 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001340 assert(isRegShiftedReg() &&
1341 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachac798e12011-07-25 20:49:51 +00001342 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1343 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001344 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachac798e12011-07-25 20:49:51 +00001345 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001346 }
1347
Jim Grosbachac798e12011-07-25 20:49:51 +00001348 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson04912702011-07-21 23:38:37 +00001349 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001350 assert(isRegShiftedImm() &&
1351 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachac798e12011-07-25 20:49:51 +00001352 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Andersonb595ed02011-07-21 18:54:16 +00001353 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachac798e12011-07-25 20:49:51 +00001354 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Andersonb595ed02011-07-21 18:54:16 +00001355 }
1356
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001357 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001358 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001359 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1360 ShifterImm.Imm));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001361 }
1362
Bill Wendling8d2aa032010-11-08 23:49:57 +00001363 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling2cae3272010-11-09 22:44:22 +00001364 assert(N == 1 && "Invalid number of operands!");
Bill Wendlingbed94652010-11-09 23:28:44 +00001365 const SmallVectorImpl<unsigned> &RegList = getRegList();
1366 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00001367 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1368 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling8d2aa032010-11-08 23:49:57 +00001369 }
1370
Bill Wendling9898ac92010-11-17 04:32:08 +00001371 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1372 addRegListOperands(Inst, N);
1373 }
1374
1375 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1376 addRegListOperands(Inst, N);
1377 }
1378
Jim Grosbach833b9d32011-07-27 20:15:40 +00001379 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1380 assert(N == 1 && "Invalid number of operands!");
1381 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1382 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1383 }
1384
Jim Grosbach864b6092011-07-28 21:34:26 +00001385 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1386 assert(N == 1 && "Invalid number of operands!");
1387 // Munge the lsb/width into a bitfield mask.
1388 unsigned lsb = Bitfield.LSB;
1389 unsigned width = Bitfield.Width;
1390 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1391 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1392 (32 - (lsb + width)));
1393 Inst.addOperand(MCOperand::CreateImm(Mask));
1394 }
1395
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001396 void addImmOperands(MCInst &Inst, unsigned N) const {
1397 assert(N == 1 && "Invalid number of operands!");
1398 addExpr(Inst, getImm());
1399 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00001400
Jim Grosbachea231912011-12-22 22:19:05 +00001401 void addFBits16Operands(MCInst &Inst, unsigned N) const {
1402 assert(N == 1 && "Invalid number of operands!");
1403 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1404 Inst.addOperand(MCOperand::CreateImm(16 - CE->getValue()));
1405 }
1406
1407 void addFBits32Operands(MCInst &Inst, unsigned N) const {
1408 assert(N == 1 && "Invalid number of operands!");
1409 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1410 Inst.addOperand(MCOperand::CreateImm(32 - CE->getValue()));
1411 }
1412
Jim Grosbache7fbce72011-10-03 23:38:36 +00001413 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1414 assert(N == 1 && "Invalid number of operands!");
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00001415 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1416 int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
1417 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbache7fbce72011-10-03 23:38:36 +00001418 }
1419
Jim Grosbach7db8d692011-09-08 22:07:06 +00001420 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1421 assert(N == 1 && "Invalid number of operands!");
1422 // FIXME: We really want to scale the value here, but the LDRD/STRD
1423 // instruction don't encode operands that way yet.
1424 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1425 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1426 }
1427
Jim Grosbach0a0b3072011-08-24 21:22:15 +00001428 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1429 assert(N == 1 && "Invalid number of operands!");
1430 // The immediate is scaled by four in the encoding and is stored
1431 // in the MCInst as such. Lop off the low two bits here.
1432 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1433 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1434 }
1435
1436 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1437 assert(N == 1 && "Invalid number of operands!");
1438 // The immediate is scaled by four in the encoding and is stored
1439 // in the MCInst as such. Lop off the low two bits here.
1440 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1441 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1442 }
1443
Jim Grosbach475c6db2011-07-25 23:09:14 +00001444 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1445 assert(N == 1 && "Invalid number of operands!");
1446 // The constant encodes as the immediate-1, and we store in the instruction
1447 // the bits as encoded, so subtract off one here.
1448 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1449 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1450 }
1451
Jim Grosbach801e0a32011-07-22 23:16:18 +00001452 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1453 assert(N == 1 && "Invalid number of operands!");
1454 // The constant encodes as the immediate-1, and we store in the instruction
1455 // the bits as encoded, so subtract off one here.
1456 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1457 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1458 }
1459
Jim Grosbach46dd4132011-08-17 21:51:27 +00001460 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1461 assert(N == 1 && "Invalid number of operands!");
1462 // The constant encodes as the immediate, except for 32, which encodes as
1463 // zero.
1464 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1465 unsigned Imm = CE->getValue();
1466 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1467 }
1468
Jim Grosbach27c1e252011-07-21 17:23:04 +00001469 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1470 assert(N == 1 && "Invalid number of operands!");
1471 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1472 // the instruction as well.
1473 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1474 int Val = CE->getValue();
1475 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1476 }
1477
Jim Grosbachb009a872011-10-28 22:36:30 +00001478 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1479 assert(N == 1 && "Invalid number of operands!");
1480 // The operand is actually a t2_so_imm, but we have its bitwise
1481 // negation in the assembly source, so twiddle it here.
1482 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1483 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1484 }
1485
Jim Grosbach30506252011-12-08 00:31:07 +00001486 void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1487 assert(N == 1 && "Invalid number of operands!");
1488 // The operand is actually a t2_so_imm, but we have its
1489 // negation in the assembly source, so twiddle it here.
1490 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1491 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1492 }
1493
Jim Grosbach3d785ed2011-10-28 22:50:54 +00001494 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1495 assert(N == 1 && "Invalid number of operands!");
1496 // The operand is actually a so_imm, but we have its bitwise
1497 // negation in the assembly source, so twiddle it here.
1498 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1499 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1500 }
1501
Jim Grosbach30506252011-12-08 00:31:07 +00001502 void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
1503 assert(N == 1 && "Invalid number of operands!");
1504 // The operand is actually a so_imm, but we have its
1505 // negation in the assembly source, so twiddle it here.
1506 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1507 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1508 }
1509
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001510 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1511 assert(N == 1 && "Invalid number of operands!");
1512 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1513 }
1514
Jim Grosbachd3595712011-08-03 23:50:40 +00001515 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1516 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001517 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopesf170f8b2011-03-24 21:04:58 +00001518 }
1519
Jim Grosbach94298a92012-01-18 22:46:46 +00001520 void addMemPCRelImm12Operands(MCInst &Inst, unsigned N) const {
1521 assert(N == 1 && "Invalid number of operands!");
1522 int32_t Imm = Memory.OffsetImm->getValue();
1523 // FIXME: Handle #-0
1524 if (Imm == INT32_MIN) Imm = 0;
1525 Inst.addOperand(MCOperand::CreateImm(Imm));
1526 }
1527
Jim Grosbacha95ec992011-10-11 17:29:55 +00001528 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1529 assert(N == 2 && "Invalid number of operands!");
1530 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1531 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1532 }
1533
Jim Grosbachd3595712011-08-03 23:50:40 +00001534 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1535 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001536 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1537 if (!Memory.OffsetRegNum) {
Jim Grosbachd3595712011-08-03 23:50:40 +00001538 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1539 // Special case for #-0
1540 if (Val == INT32_MIN) Val = 0;
1541 if (Val < 0) Val = -Val;
1542 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1543 } else {
1544 // For register offset, we encode the shift type and negation flag
1545 // here.
Jim Grosbach871dff72011-10-11 15:59:20 +00001546 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1547 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001548 }
Jim Grosbach871dff72011-10-11 15:59:20 +00001549 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1550 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001551 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001552 }
1553
Jim Grosbachcd17c122011-08-04 23:01:30 +00001554 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1555 assert(N == 2 && "Invalid number of operands!");
1556 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1557 assert(CE && "non-constant AM2OffsetImm operand!");
1558 int32_t Val = CE->getValue();
1559 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1560 // Special case for #-0
1561 if (Val == INT32_MIN) Val = 0;
1562 if (Val < 0) Val = -Val;
1563 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1564 Inst.addOperand(MCOperand::CreateReg(0));
1565 Inst.addOperand(MCOperand::CreateImm(Val));
1566 }
1567
Jim Grosbach5b96b802011-08-10 20:29:19 +00001568 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1569 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach8648c102011-12-19 23:06:24 +00001570 // If we have an immediate that's not a constant, treat it as a label
1571 // reference needing a fixup. If it is a constant, it's something else
1572 // and we reject it.
1573 if (isImm()) {
1574 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1575 Inst.addOperand(MCOperand::CreateReg(0));
1576 Inst.addOperand(MCOperand::CreateImm(0));
1577 return;
1578 }
1579
Jim Grosbach871dff72011-10-11 15:59:20 +00001580 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1581 if (!Memory.OffsetRegNum) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00001582 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1583 // Special case for #-0
1584 if (Val == INT32_MIN) Val = 0;
1585 if (Val < 0) Val = -Val;
1586 Val = ARM_AM::getAM3Opc(AddSub, Val);
1587 } else {
1588 // For register offset, we encode the shift type and negation flag
1589 // here.
Jim Grosbach871dff72011-10-11 15:59:20 +00001590 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach5b96b802011-08-10 20:29:19 +00001591 }
Jim Grosbach871dff72011-10-11 15:59:20 +00001592 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1593 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach5b96b802011-08-10 20:29:19 +00001594 Inst.addOperand(MCOperand::CreateImm(Val));
1595 }
1596
1597 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1598 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001599 if (Kind == k_PostIndexRegister) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00001600 int32_t Val =
1601 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1602 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1603 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001604 return;
Jim Grosbach5b96b802011-08-10 20:29:19 +00001605 }
1606
1607 // Constant offset.
1608 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1609 int32_t Val = CE->getValue();
1610 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1611 // Special case for #-0
1612 if (Val == INT32_MIN) Val = 0;
1613 if (Val < 0) Val = -Val;
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001614 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach5b96b802011-08-10 20:29:19 +00001615 Inst.addOperand(MCOperand::CreateReg(0));
1616 Inst.addOperand(MCOperand::CreateImm(Val));
1617 }
1618
Jim Grosbachd3595712011-08-03 23:50:40 +00001619 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1620 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachfb2f1d62011-11-01 01:24:45 +00001621 // If we have an immediate that's not a constant, treat it as a label
1622 // reference needing a fixup. If it is a constant, it's something else
1623 // and we reject it.
1624 if (isImm()) {
1625 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1626 Inst.addOperand(MCOperand::CreateImm(0));
1627 return;
1628 }
1629
Jim Grosbachd3595712011-08-03 23:50:40 +00001630 // The lower two bits are always zero and as such are not encoded.
Jim Grosbach871dff72011-10-11 15:59:20 +00001631 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00001632 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1633 // Special case for #-0
1634 if (Val == INT32_MIN) Val = 0;
1635 if (Val < 0) Val = -Val;
1636 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbach871dff72011-10-11 15:59:20 +00001637 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001638 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00001639 }
1640
Jim Grosbach7db8d692011-09-08 22:07:06 +00001641 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1642 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach8648c102011-12-19 23:06:24 +00001643 // If we have an immediate that's not a constant, treat it as a label
1644 // reference needing a fixup. If it is a constant, it's something else
1645 // and we reject it.
1646 if (isImm()) {
1647 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1648 Inst.addOperand(MCOperand::CreateImm(0));
1649 return;
1650 }
1651
Jim Grosbach871dff72011-10-11 15:59:20 +00001652 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1653 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7db8d692011-09-08 22:07:06 +00001654 Inst.addOperand(MCOperand::CreateImm(Val));
1655 }
1656
Jim Grosbacha05627e2011-09-09 18:37:27 +00001657 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1658 assert(N == 2 && "Invalid number of operands!");
1659 // The lower two bits are always zero and as such are not encoded.
Jim Grosbach871dff72011-10-11 15:59:20 +00001660 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1661 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha05627e2011-09-09 18:37:27 +00001662 Inst.addOperand(MCOperand::CreateImm(Val));
1663 }
1664
Jim Grosbachd3595712011-08-03 23:50:40 +00001665 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1666 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001667 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1668 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001669 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner5d6f6a02010-10-29 00:27:31 +00001670 }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001671
Jim Grosbach2392c532011-09-07 23:39:14 +00001672 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1673 addMemImm8OffsetOperands(Inst, N);
1674 }
1675
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001676 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach2392c532011-09-07 23:39:14 +00001677 addMemImm8OffsetOperands(Inst, N);
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001678 }
1679
1680 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1681 assert(N == 2 && "Invalid number of operands!");
1682 // If this is an immediate, it's a label reference.
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001683 if (isImm()) {
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001684 addExpr(Inst, getImm());
1685 Inst.addOperand(MCOperand::CreateImm(0));
1686 return;
1687 }
1688
1689 // Otherwise, it's a normal memory reg+offset.
Jim Grosbach871dff72011-10-11 15:59:20 +00001690 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1691 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001692 Inst.addOperand(MCOperand::CreateImm(Val));
1693 }
1694
Jim Grosbachd3595712011-08-03 23:50:40 +00001695 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1696 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach95466ce2011-08-08 20:59:31 +00001697 // If this is an immediate, it's a label reference.
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001698 if (isImm()) {
Jim Grosbach95466ce2011-08-08 20:59:31 +00001699 addExpr(Inst, getImm());
1700 Inst.addOperand(MCOperand::CreateImm(0));
1701 return;
1702 }
1703
1704 // Otherwise, it's a normal memory reg+offset.
Jim Grosbach871dff72011-10-11 15:59:20 +00001705 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1706 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001707 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendling092a7bd2010-12-14 03:36:38 +00001708 }
Bill Wendling811c9362010-11-30 07:44:32 +00001709
Jim Grosbach05541f42011-09-19 22:21:13 +00001710 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1711 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001712 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1713 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach05541f42011-09-19 22:21:13 +00001714 }
1715
1716 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1717 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001718 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1719 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach05541f42011-09-19 22:21:13 +00001720 }
1721
Jim Grosbachd3595712011-08-03 23:50:40 +00001722 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1723 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001724 unsigned Val =
1725 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1726 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbach871dff72011-10-11 15:59:20 +00001727 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1728 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001729 Inst.addOperand(MCOperand::CreateImm(Val));
1730 }
1731
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001732 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1733 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001734 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1735 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1736 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001737 }
1738
Jim Grosbachd3595712011-08-03 23:50:40 +00001739 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1740 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001741 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1742 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001743 }
1744
Jim Grosbach3fe94e32011-08-19 17:55:24 +00001745 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1746 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001747 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1748 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach3fe94e32011-08-19 17:55:24 +00001749 Inst.addOperand(MCOperand::CreateImm(Val));
1750 }
1751
Jim Grosbach26d35872011-08-19 18:55:51 +00001752 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1753 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001754 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1755 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach26d35872011-08-19 18:55:51 +00001756 Inst.addOperand(MCOperand::CreateImm(Val));
1757 }
1758
Jim Grosbacha32c7532011-08-19 18:49:59 +00001759 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1760 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001761 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1762 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha32c7532011-08-19 18:49:59 +00001763 Inst.addOperand(MCOperand::CreateImm(Val));
1764 }
1765
Jim Grosbach23983d62011-08-19 18:13:48 +00001766 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1767 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001768 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1769 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach23983d62011-08-19 18:13:48 +00001770 Inst.addOperand(MCOperand::CreateImm(Val));
1771 }
1772
Jim Grosbachd3595712011-08-03 23:50:40 +00001773 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1774 assert(N == 1 && "Invalid number of operands!");
1775 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1776 assert(CE && "non-constant post-idx-imm8 operand!");
1777 int Imm = CE->getValue();
1778 bool isAdd = Imm >= 0;
Owen Andersonf02d98d2011-08-29 17:17:09 +00001779 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00001780 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1781 Inst.addOperand(MCOperand::CreateImm(Imm));
1782 }
1783
Jim Grosbach93981412011-10-11 21:55:36 +00001784 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1785 assert(N == 1 && "Invalid number of operands!");
1786 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1787 assert(CE && "non-constant post-idx-imm8s4 operand!");
1788 int Imm = CE->getValue();
1789 bool isAdd = Imm >= 0;
1790 if (Imm == INT32_MIN) Imm = 0;
1791 // Immediate is scaled by 4.
1792 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1793 Inst.addOperand(MCOperand::CreateImm(Imm));
1794 }
1795
Jim Grosbachd3595712011-08-03 23:50:40 +00001796 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1797 assert(N == 2 && "Invalid number of operands!");
1798 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachc320c852011-08-05 21:28:30 +00001799 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1800 }
1801
1802 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1803 assert(N == 2 && "Invalid number of operands!");
1804 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1805 // The sign, shift type, and shift amount are encoded in a single operand
1806 // using the AM2 encoding helpers.
1807 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1808 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1809 PostIdxReg.ShiftTy);
1810 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendling811c9362010-11-30 07:44:32 +00001811 }
1812
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001813 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1814 assert(N == 1 && "Invalid number of operands!");
1815 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1816 }
1817
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001818 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1819 assert(N == 1 && "Invalid number of operands!");
1820 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1821 }
1822
Jim Grosbach182b6a02011-11-29 23:51:09 +00001823 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001824 assert(N == 1 && "Invalid number of operands!");
1825 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1826 }
1827
Jim Grosbach04945c42011-12-02 00:35:16 +00001828 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1829 assert(N == 2 && "Invalid number of operands!");
1830 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1831 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1832 }
1833
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001834 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1835 assert(N == 1 && "Invalid number of operands!");
1836 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1837 }
1838
1839 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1840 assert(N == 1 && "Invalid number of operands!");
1841 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1842 }
1843
1844 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1845 assert(N == 1 && "Invalid number of operands!");
1846 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1847 }
1848
Jim Grosbach741cd732011-10-17 22:26:03 +00001849 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1850 assert(N == 1 && "Invalid number of operands!");
1851 // The immediate encodes the type of constant as well as the value.
1852 // Mask in that this is an i8 splat.
1853 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1854 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1855 }
1856
Jim Grosbachcda32ae2011-10-17 23:09:09 +00001857 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1858 assert(N == 1 && "Invalid number of operands!");
1859 // The immediate encodes the type of constant as well as the value.
1860 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1861 unsigned Value = CE->getValue();
1862 if (Value >= 256)
1863 Value = (Value >> 8) | 0xa00;
1864 else
1865 Value |= 0x800;
1866 Inst.addOperand(MCOperand::CreateImm(Value));
1867 }
1868
Jim Grosbach8211c052011-10-18 00:22:00 +00001869 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1870 assert(N == 1 && "Invalid number of operands!");
1871 // The immediate encodes the type of constant as well as the value.
1872 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1873 unsigned Value = CE->getValue();
1874 if (Value >= 256 && Value <= 0xff00)
1875 Value = (Value >> 8) | 0x200;
1876 else if (Value > 0xffff && Value <= 0xff0000)
1877 Value = (Value >> 16) | 0x400;
1878 else if (Value > 0xffffff)
1879 Value = (Value >> 24) | 0x600;
1880 Inst.addOperand(MCOperand::CreateImm(Value));
1881 }
1882
1883 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1884 assert(N == 1 && "Invalid number of operands!");
1885 // The immediate encodes the type of constant as well as the value.
1886 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1887 unsigned Value = CE->getValue();
1888 if (Value >= 256 && Value <= 0xffff)
1889 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1890 else if (Value > 0xffff && Value <= 0xffffff)
1891 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1892 else if (Value > 0xffffff)
1893 Value = (Value >> 24) | 0x600;
1894 Inst.addOperand(MCOperand::CreateImm(Value));
1895 }
1896
Jim Grosbach045b6c72011-12-19 23:51:07 +00001897 void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const {
1898 assert(N == 1 && "Invalid number of operands!");
1899 // The immediate encodes the type of constant as well as the value.
1900 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1901 unsigned Value = ~CE->getValue();
1902 if (Value >= 256 && Value <= 0xffff)
1903 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1904 else if (Value > 0xffff && Value <= 0xffffff)
1905 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1906 else if (Value > 0xffffff)
1907 Value = (Value >> 24) | 0x600;
1908 Inst.addOperand(MCOperand::CreateImm(Value));
1909 }
1910
Jim Grosbache4454e02011-10-18 16:18:11 +00001911 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1912 assert(N == 1 && "Invalid number of operands!");
1913 // The immediate encodes the type of constant as well as the value.
1914 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1915 uint64_t Value = CE->getValue();
1916 unsigned Imm = 0;
1917 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1918 Imm |= (Value & 1) << i;
1919 }
1920 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1921 }
1922
Jim Grosbach602aa902011-07-13 15:34:57 +00001923 virtual void print(raw_ostream &OS) const;
Daniel Dunbarebace222010-08-11 06:37:04 +00001924
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001925 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001926 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001927 Op->ITMask.Mask = Mask;
1928 Op->StartLoc = S;
1929 Op->EndLoc = S;
1930 return Op;
1931 }
1932
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001933 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001934 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001935 Op->CC.Val = CC;
1936 Op->StartLoc = S;
1937 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001938 return Op;
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001939 }
1940
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001941 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001942 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001943 Op->Cop.Val = CopVal;
1944 Op->StartLoc = S;
1945 Op->EndLoc = S;
1946 return Op;
1947 }
1948
1949 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001950 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001951 Op->Cop.Val = CopVal;
1952 Op->StartLoc = S;
1953 Op->EndLoc = S;
1954 return Op;
1955 }
1956
Jim Grosbach48399582011-10-12 17:34:41 +00001957 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1958 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1959 Op->Cop.Val = Val;
1960 Op->StartLoc = S;
1961 Op->EndLoc = E;
1962 return Op;
1963 }
1964
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001965 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001966 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001967 Op->Reg.RegNum = RegNum;
1968 Op->StartLoc = S;
1969 Op->EndLoc = S;
1970 return Op;
1971 }
1972
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001973 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001974 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001975 Op->Tok.Data = Str.data();
1976 Op->Tok.Length = Str.size();
1977 Op->StartLoc = S;
1978 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001979 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001980 }
1981
Bill Wendling2063b842010-11-18 23:43:05 +00001982 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001983 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001984 Op->Reg.RegNum = RegNum;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001985 Op->StartLoc = S;
1986 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001987 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001988 }
1989
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001990 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1991 unsigned SrcReg,
1992 unsigned ShiftReg,
1993 unsigned ShiftImm,
1994 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001995 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachac798e12011-07-25 20:49:51 +00001996 Op->RegShiftedReg.ShiftTy = ShTy;
1997 Op->RegShiftedReg.SrcReg = SrcReg;
1998 Op->RegShiftedReg.ShiftReg = ShiftReg;
1999 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002000 Op->StartLoc = S;
2001 Op->EndLoc = E;
2002 return Op;
2003 }
2004
Owen Andersonb595ed02011-07-21 18:54:16 +00002005 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
2006 unsigned SrcReg,
2007 unsigned ShiftImm,
2008 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002009 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachac798e12011-07-25 20:49:51 +00002010 Op->RegShiftedImm.ShiftTy = ShTy;
2011 Op->RegShiftedImm.SrcReg = SrcReg;
2012 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Andersonb595ed02011-07-21 18:54:16 +00002013 Op->StartLoc = S;
2014 Op->EndLoc = E;
2015 return Op;
2016 }
2017
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002018 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002019 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002020 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002021 Op->ShifterImm.isASR = isASR;
2022 Op->ShifterImm.Imm = Imm;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002023 Op->StartLoc = S;
2024 Op->EndLoc = E;
2025 return Op;
2026 }
2027
Jim Grosbach833b9d32011-07-27 20:15:40 +00002028 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002029 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach833b9d32011-07-27 20:15:40 +00002030 Op->RotImm.Imm = Imm;
2031 Op->StartLoc = S;
2032 Op->EndLoc = E;
2033 return Op;
2034 }
2035
Jim Grosbach864b6092011-07-28 21:34:26 +00002036 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
2037 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002038 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach864b6092011-07-28 21:34:26 +00002039 Op->Bitfield.LSB = LSB;
2040 Op->Bitfield.Width = Width;
2041 Op->StartLoc = S;
2042 Op->EndLoc = E;
2043 return Op;
2044 }
2045
Bill Wendling2cae3272010-11-09 22:44:22 +00002046 static ARMOperand *
Bill Wendlingbed94652010-11-09 23:28:44 +00002047 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00002048 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002049 KindTy Kind = k_RegisterList;
Bill Wendling9898ac92010-11-17 04:32:08 +00002050
Jim Grosbach75461af2011-09-13 22:56:44 +00002051 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002052 Kind = k_DPRRegisterList;
Jim Grosbach75461af2011-09-13 22:56:44 +00002053 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng9eec7642011-07-25 21:32:49 +00002054 contains(Regs.front().first))
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002055 Kind = k_SPRRegisterList;
Bill Wendling9898ac92010-11-17 04:32:08 +00002056
2057 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendlingbed94652010-11-09 23:28:44 +00002058 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00002059 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling0ab0f672010-11-18 21:50:54 +00002060 Op->Registers.push_back(I->first);
Bill Wendling20b5ea982010-11-19 00:38:19 +00002061 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00002062 Op->StartLoc = StartLoc;
2063 Op->EndLoc = EndLoc;
Bill Wendling7cef4472010-11-06 19:56:04 +00002064 return Op;
2065 }
2066
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002067 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
Jim Grosbach2f50e922011-12-15 21:44:33 +00002068 bool isDoubleSpaced, SMLoc S, SMLoc E) {
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002069 ARMOperand *Op = new ARMOperand(k_VectorList);
2070 Op->VectorList.RegNum = RegNum;
2071 Op->VectorList.Count = Count;
Jim Grosbach2f50e922011-12-15 21:44:33 +00002072 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002073 Op->StartLoc = S;
2074 Op->EndLoc = E;
2075 return Op;
2076 }
2077
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002078 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
Jim Grosbachc5af54e2011-12-21 00:38:54 +00002079 bool isDoubleSpaced,
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002080 SMLoc S, SMLoc E) {
2081 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
2082 Op->VectorList.RegNum = RegNum;
2083 Op->VectorList.Count = Count;
Jim Grosbachc5af54e2011-12-21 00:38:54 +00002084 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002085 Op->StartLoc = S;
2086 Op->EndLoc = E;
2087 return Op;
2088 }
2089
Jim Grosbach04945c42011-12-02 00:35:16 +00002090 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
Jim Grosbach75e2ab52011-12-20 19:21:26 +00002091 unsigned Index,
2092 bool isDoubleSpaced,
2093 SMLoc S, SMLoc E) {
Jim Grosbach04945c42011-12-02 00:35:16 +00002094 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
2095 Op->VectorList.RegNum = RegNum;
2096 Op->VectorList.Count = Count;
2097 Op->VectorList.LaneIndex = Index;
Jim Grosbach75e2ab52011-12-20 19:21:26 +00002098 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach04945c42011-12-02 00:35:16 +00002099 Op->StartLoc = S;
2100 Op->EndLoc = E;
2101 return Op;
2102 }
2103
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002104 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
2105 MCContext &Ctx) {
2106 ARMOperand *Op = new ARMOperand(k_VectorIndex);
2107 Op->VectorIndex.Val = Idx;
2108 Op->StartLoc = S;
2109 Op->EndLoc = E;
2110 return Op;
2111 }
2112
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002113 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002114 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002115 Op->Imm.Val = Val;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002116 Op->StartLoc = S;
2117 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002118 return Op;
Kevin Enderbyf5079942009-10-13 22:19:02 +00002119 }
2120
Jim Grosbachd3595712011-08-03 23:50:40 +00002121 static ARMOperand *CreateMem(unsigned BaseRegNum,
2122 const MCConstantExpr *OffsetImm,
2123 unsigned OffsetRegNum,
2124 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00002125 unsigned ShiftImm,
Jim Grosbacha95ec992011-10-11 17:29:55 +00002126 unsigned Alignment,
Jim Grosbachd3595712011-08-03 23:50:40 +00002127 bool isNegative,
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002128 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002129 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbach871dff72011-10-11 15:59:20 +00002130 Op->Memory.BaseRegNum = BaseRegNum;
2131 Op->Memory.OffsetImm = OffsetImm;
2132 Op->Memory.OffsetRegNum = OffsetRegNum;
2133 Op->Memory.ShiftType = ShiftType;
2134 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbacha95ec992011-10-11 17:29:55 +00002135 Op->Memory.Alignment = Alignment;
Jim Grosbach871dff72011-10-11 15:59:20 +00002136 Op->Memory.isNegative = isNegative;
Jim Grosbachd3595712011-08-03 23:50:40 +00002137 Op->StartLoc = S;
2138 Op->EndLoc = E;
2139 return Op;
2140 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00002141
Jim Grosbachc320c852011-08-05 21:28:30 +00002142 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
2143 ARM_AM::ShiftOpc ShiftTy,
2144 unsigned ShiftImm,
Jim Grosbachd3595712011-08-03 23:50:40 +00002145 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002146 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbachd3595712011-08-03 23:50:40 +00002147 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachc320c852011-08-05 21:28:30 +00002148 Op->PostIdxReg.isAdd = isAdd;
2149 Op->PostIdxReg.ShiftTy = ShiftTy;
2150 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002151 Op->StartLoc = S;
2152 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002153 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002154 }
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002155
2156 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002157 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002158 Op->MBOpt.Val = Opt;
2159 Op->StartLoc = S;
2160 Op->EndLoc = S;
2161 return Op;
2162 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002163
2164 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002165 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002166 Op->IFlags.Val = IFlags;
2167 Op->StartLoc = S;
2168 Op->EndLoc = S;
2169 return Op;
2170 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002171
2172 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002173 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002174 Op->MMask.Val = MMask;
2175 Op->StartLoc = S;
2176 Op->EndLoc = S;
2177 return Op;
2178 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002179};
2180
2181} // end anonymous namespace.
2182
Jim Grosbach602aa902011-07-13 15:34:57 +00002183void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002184 switch (Kind) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002185 case k_CondCode:
Daniel Dunbar2be732a2011-01-10 15:26:21 +00002186 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002187 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002188 case k_CCOut:
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00002189 OS << "<ccout " << getReg() << ">";
2190 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002191 case k_ITCondMask: {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00002192 static const char *MaskStr[] = {
2193 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2194 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2195 };
Jim Grosbach3d1eac82011-08-26 21:43:41 +00002196 assert((ITMask.Mask & 0xf) == ITMask.Mask);
2197 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2198 break;
2199 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002200 case k_CoprocNum:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002201 OS << "<coprocessor number: " << getCoproc() << ">";
2202 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002203 case k_CoprocReg:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002204 OS << "<coprocessor register: " << getCoproc() << ">";
2205 break;
Jim Grosbach48399582011-10-12 17:34:41 +00002206 case k_CoprocOption:
2207 OS << "<coprocessor option: " << CoprocOption.Val << ">";
2208 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002209 case k_MSRMask:
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002210 OS << "<mask: " << getMSRMask() << ">";
2211 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002212 case k_Immediate:
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002213 getImm()->print(OS);
2214 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002215 case k_MemBarrierOpt:
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002216 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2217 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002218 case k_Memory:
Daniel Dunbarbcd8eb02011-01-18 05:55:21 +00002219 OS << "<memory "
Jim Grosbach871dff72011-10-11 15:59:20 +00002220 << " base:" << Memory.BaseRegNum;
Daniel Dunbarbcd8eb02011-01-18 05:55:21 +00002221 OS << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002222 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002223 case k_PostIndexRegister:
Jim Grosbachc320c852011-08-05 21:28:30 +00002224 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2225 << PostIdxReg.RegNum;
2226 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2227 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2228 << PostIdxReg.ShiftImm;
2229 OS << ">";
Jim Grosbachd3595712011-08-03 23:50:40 +00002230 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002231 case k_ProcIFlags: {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002232 OS << "<ARM_PROC::";
2233 unsigned IFlags = getProcIFlags();
2234 for (int i=2; i >= 0; --i)
2235 if (IFlags & (1 << i))
2236 OS << ARM_PROC::IFlagsToString(1 << i);
2237 OS << ">";
2238 break;
2239 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002240 case k_Register:
Bill Wendling2063b842010-11-18 23:43:05 +00002241 OS << "<register " << getReg() << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002242 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002243 case k_ShifterImmediate:
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002244 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2245 << " #" << ShifterImm.Imm << ">";
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002246 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002247 case k_ShiftedRegister:
Owen Andersonb595ed02011-07-21 18:54:16 +00002248 OS << "<so_reg_reg "
Jim Grosbach01e04392011-11-16 21:46:50 +00002249 << RegShiftedReg.SrcReg << " "
2250 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2251 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002252 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002253 case k_ShiftedImmediate:
Owen Andersonb595ed02011-07-21 18:54:16 +00002254 OS << "<so_reg_imm "
Jim Grosbach01e04392011-11-16 21:46:50 +00002255 << RegShiftedImm.SrcReg << " "
2256 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2257 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Andersonb595ed02011-07-21 18:54:16 +00002258 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002259 case k_RotateImmediate:
Jim Grosbach833b9d32011-07-27 20:15:40 +00002260 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2261 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002262 case k_BitfieldDescriptor:
Jim Grosbach864b6092011-07-28 21:34:26 +00002263 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2264 << ", width: " << Bitfield.Width << ">";
2265 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002266 case k_RegisterList:
2267 case k_DPRRegisterList:
2268 case k_SPRRegisterList: {
Bill Wendling7cef4472010-11-06 19:56:04 +00002269 OS << "<register_list ";
Bill Wendling7cef4472010-11-06 19:56:04 +00002270
Bill Wendlingbed94652010-11-09 23:28:44 +00002271 const SmallVectorImpl<unsigned> &RegList = getRegList();
2272 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00002273 I = RegList.begin(), E = RegList.end(); I != E; ) {
2274 OS << *I;
2275 if (++I < E) OS << ", ";
Bill Wendling7cef4472010-11-06 19:56:04 +00002276 }
2277
2278 OS << ">";
2279 break;
2280 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002281 case k_VectorList:
2282 OS << "<vector_list " << VectorList.Count << " * "
2283 << VectorList.RegNum << ">";
2284 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002285 case k_VectorListAllLanes:
2286 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2287 << VectorList.RegNum << ">";
2288 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00002289 case k_VectorListIndexed:
2290 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2291 << VectorList.Count << " * " << VectorList.RegNum << ">";
2292 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002293 case k_Token:
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002294 OS << "'" << getToken() << "'";
2295 break;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002296 case k_VectorIndex:
2297 OS << "<vectorindex " << getVectorIndex() << ">";
2298 break;
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002299 }
2300}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00002301
2302/// @name Auto-generated Match Functions
2303/// {
2304
2305static unsigned MatchRegisterName(StringRef Name);
2306
2307/// }
2308
Bob Wilsonfb0bd042011-02-03 21:46:10 +00002309bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2310 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbachab5830e2011-12-14 02:16:11 +00002311 StartLoc = Parser.getTok().getLoc();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002312 RegNo = tryParseRegister();
Jim Grosbachab5830e2011-12-14 02:16:11 +00002313 EndLoc = Parser.getTok().getLoc();
Roman Divacky36b1b472011-01-27 17:14:22 +00002314
2315 return (RegNo == (unsigned)-1);
2316}
2317
Kevin Enderby8be42bd2009-10-30 22:55:57 +00002318/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattner44e5981c2010-10-30 04:09:10 +00002319/// and if it is a register name the token is eaten and the register number is
2320/// returned. Otherwise return -1.
2321///
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002322int ARMAsmParser::tryParseRegister() {
Chris Lattner44e5981c2010-10-30 04:09:10 +00002323 const AsmToken &Tok = Parser.getTok();
Jim Grosbachd3595712011-08-03 23:50:40 +00002324 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbach99710a82010-11-01 16:44:21 +00002325
Benjamin Kramer20baffb2011-11-06 20:37:06 +00002326 std::string lowerCase = Tok.getString().lower();
Owen Andersona098d152011-01-13 22:50:36 +00002327 unsigned RegNum = MatchRegisterName(lowerCase);
2328 if (!RegNum) {
2329 RegNum = StringSwitch<unsigned>(lowerCase)
2330 .Case("r13", ARM::SP)
2331 .Case("r14", ARM::LR)
2332 .Case("r15", ARM::PC)
2333 .Case("ip", ARM::R12)
Jim Grosbach4edc7362011-12-08 19:27:38 +00002334 // Additional register name aliases for 'gas' compatibility.
2335 .Case("a1", ARM::R0)
2336 .Case("a2", ARM::R1)
2337 .Case("a3", ARM::R2)
2338 .Case("a4", ARM::R3)
2339 .Case("v1", ARM::R4)
2340 .Case("v2", ARM::R5)
2341 .Case("v3", ARM::R6)
2342 .Case("v4", ARM::R7)
2343 .Case("v5", ARM::R8)
2344 .Case("v6", ARM::R9)
2345 .Case("v7", ARM::R10)
2346 .Case("v8", ARM::R11)
2347 .Case("sb", ARM::R9)
2348 .Case("sl", ARM::R10)
2349 .Case("fp", ARM::R11)
Owen Andersona098d152011-01-13 22:50:36 +00002350 .Default(0);
2351 }
Jim Grosbachab5830e2011-12-14 02:16:11 +00002352 if (!RegNum) {
Jim Grosbachcd22e4a2011-12-20 23:11:00 +00002353 // Check for aliases registered via .req. Canonicalize to lower case.
2354 // That's more consistent since register names are case insensitive, and
2355 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2356 StringMap<unsigned>::const_iterator Entry = RegisterReqs.find(lowerCase);
Jim Grosbachab5830e2011-12-14 02:16:11 +00002357 // If no match, return failure.
2358 if (Entry == RegisterReqs.end())
2359 return -1;
2360 Parser.Lex(); // Eat identifier token.
2361 return Entry->getValue();
2362 }
Bob Wilsonfb0bd042011-02-03 21:46:10 +00002363
Chris Lattner44e5981c2010-10-30 04:09:10 +00002364 Parser.Lex(); // Eat identifier token.
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002365
Chris Lattner44e5981c2010-10-30 04:09:10 +00002366 return RegNum;
2367}
Jim Grosbach99710a82010-11-01 16:44:21 +00002368
Jim Grosbachbb24c592011-07-13 18:49:30 +00002369// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2370// If a recoverable error occurs, return 1. If an irrecoverable error
2371// occurs, return -1. An irrecoverable error is one where tokens have been
2372// consumed in the process of trying to parse the shifter (i.e., when it is
2373// indeed a shifter operand, but malformed).
Jim Grosbach0d6022d2011-07-26 20:41:24 +00002374int ARMAsmParser::tryParseShiftRegister(
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002375 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2376 SMLoc S = Parser.getTok().getLoc();
2377 const AsmToken &Tok = Parser.getTok();
2378 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2379
Benjamin Kramer20baffb2011-11-06 20:37:06 +00002380 std::string lowerCase = Tok.getString().lower();
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002381 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbach3b559ff2011-12-07 23:40:58 +00002382 .Case("asl", ARM_AM::lsl)
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002383 .Case("lsl", ARM_AM::lsl)
2384 .Case("lsr", ARM_AM::lsr)
2385 .Case("asr", ARM_AM::asr)
2386 .Case("ror", ARM_AM::ror)
2387 .Case("rrx", ARM_AM::rrx)
2388 .Default(ARM_AM::no_shift);
2389
2390 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbachbb24c592011-07-13 18:49:30 +00002391 return 1;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002392
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002393 Parser.Lex(); // Eat the operator.
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002394
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002395 // The source register for the shift has already been added to the
2396 // operand list, so we need to pop it off and combine it into the shifted
2397 // register operand instead.
Benjamin Kramer1757e7a2011-07-14 18:41:22 +00002398 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002399 if (!PrevOp->isReg())
2400 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2401 int SrcReg = PrevOp->getReg();
2402 int64_t Imm = 0;
2403 int ShiftReg = 0;
2404 if (ShiftTy == ARM_AM::rrx) {
2405 // RRX Doesn't have an explicit shift amount. The encoder expects
2406 // the shift register to be the same as the source register. Seems odd,
2407 // but OK.
2408 ShiftReg = SrcReg;
2409 } else {
2410 // Figure out if this is shifted by a constant or a register (for non-RRX).
Jim Grosbachef70e9b2011-12-09 22:25:03 +00002411 if (Parser.getTok().is(AsmToken::Hash) ||
2412 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002413 Parser.Lex(); // Eat hash.
2414 SMLoc ImmLoc = Parser.getTok().getLoc();
2415 const MCExpr *ShiftExpr = 0;
Jim Grosbachbb24c592011-07-13 18:49:30 +00002416 if (getParser().ParseExpression(ShiftExpr)) {
2417 Error(ImmLoc, "invalid immediate shift value");
2418 return -1;
2419 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002420 // The expression must be evaluatable as an immediate.
2421 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbachbb24c592011-07-13 18:49:30 +00002422 if (!CE) {
2423 Error(ImmLoc, "invalid immediate shift value");
2424 return -1;
2425 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002426 // Range check the immediate.
2427 // lsl, ror: 0 <= imm <= 31
2428 // lsr, asr: 0 <= imm <= 32
2429 Imm = CE->getValue();
2430 if (Imm < 0 ||
2431 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2432 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbachbb24c592011-07-13 18:49:30 +00002433 Error(ImmLoc, "immediate shift value out of range");
2434 return -1;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002435 }
Jim Grosbach21488b82011-12-22 17:37:00 +00002436 // shift by zero is a nop. Always send it through as lsl.
2437 // ('as' compatibility)
2438 if (Imm == 0)
2439 ShiftTy = ARM_AM::lsl;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002440 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002441 ShiftReg = tryParseRegister();
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002442 SMLoc L = Parser.getTok().getLoc();
Jim Grosbachbb24c592011-07-13 18:49:30 +00002443 if (ShiftReg == -1) {
2444 Error (L, "expected immediate or register in shift operand");
2445 return -1;
2446 }
2447 } else {
2448 Error (Parser.getTok().getLoc(),
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002449 "expected immediate or register in shift operand");
Jim Grosbachbb24c592011-07-13 18:49:30 +00002450 return -1;
2451 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002452 }
2453
Owen Andersonb595ed02011-07-21 18:54:16 +00002454 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2455 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachac798e12011-07-25 20:49:51 +00002456 ShiftReg, Imm,
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002457 S, Parser.getTok().getLoc()));
Owen Andersonb595ed02011-07-21 18:54:16 +00002458 else
2459 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2460 S, Parser.getTok().getLoc()));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002461
Jim Grosbachbb24c592011-07-13 18:49:30 +00002462 return 0;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002463}
2464
2465
Bill Wendling2063b842010-11-18 23:43:05 +00002466/// Try to parse a register name. The token must be an Identifier when called.
2467/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2468/// if there is a "writeback". 'true' if it's not a register.
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002469///
Kevin Enderby8be42bd2009-10-30 22:55:57 +00002470/// TODO this is likely to change to allow different register types and or to
2471/// parse for a specific register type.
Bill Wendling2063b842010-11-18 23:43:05 +00002472bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002473tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattner44e5981c2010-10-30 04:09:10 +00002474 SMLoc S = Parser.getTok().getLoc();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002475 int RegNo = tryParseRegister();
Bill Wendlinge18980a2010-11-06 22:36:58 +00002476 if (RegNo == -1)
Bill Wendling2063b842010-11-18 23:43:05 +00002477 return true;
Jim Grosbach99710a82010-11-01 16:44:21 +00002478
Bill Wendling2063b842010-11-18 23:43:05 +00002479 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002480
Chris Lattner44e5981c2010-10-30 04:09:10 +00002481 const AsmToken &ExclaimTok = Parser.getTok();
2482 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling2063b842010-11-18 23:43:05 +00002483 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2484 ExclaimTok.getLoc()));
Chris Lattner44e5981c2010-10-30 04:09:10 +00002485 Parser.Lex(); // Eat exclaim token
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002486 return false;
2487 }
2488
2489 // Also check for an index operand. This is only legal for vector registers,
2490 // but that'll get caught OK in operand matching, so we don't need to
2491 // explicitly filter everything else out here.
2492 if (Parser.getTok().is(AsmToken::LBrac)) {
2493 SMLoc SIdx = Parser.getTok().getLoc();
2494 Parser.Lex(); // Eat left bracket token.
2495
2496 const MCExpr *ImmVal;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002497 if (getParser().ParseExpression(ImmVal))
2498 return MatchOperand_ParseFail;
2499 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2500 if (!MCE) {
2501 TokError("immediate value expected for vector index");
2502 return MatchOperand_ParseFail;
2503 }
2504
2505 SMLoc E = Parser.getTok().getLoc();
2506 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2507 Error(E, "']' expected");
2508 return MatchOperand_ParseFail;
2509 }
2510
2511 Parser.Lex(); // Eat right bracket token.
2512
2513 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2514 SIdx, E,
2515 getContext()));
Kevin Enderby2207e5f2009-10-07 18:01:35 +00002516 }
2517
Bill Wendling2063b842010-11-18 23:43:05 +00002518 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002519}
2520
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002521/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2522/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2523/// "c5", ...
2524static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002525 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2526 // but efficient.
2527 switch (Name.size()) {
David Blaikie46a9f012012-01-20 21:51:11 +00002528 default: return -1;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002529 case 2:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002530 if (Name[0] != CoprocOp)
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002531 return -1;
2532 switch (Name[1]) {
2533 default: return -1;
2534 case '0': return 0;
2535 case '1': return 1;
2536 case '2': return 2;
2537 case '3': return 3;
2538 case '4': return 4;
2539 case '5': return 5;
2540 case '6': return 6;
2541 case '7': return 7;
2542 case '8': return 8;
2543 case '9': return 9;
2544 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002545 case 3:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002546 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002547 return -1;
2548 switch (Name[2]) {
2549 default: return -1;
2550 case '0': return 10;
2551 case '1': return 11;
2552 case '2': return 12;
2553 case '3': return 13;
2554 case '4': return 14;
2555 case '5': return 15;
2556 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002557 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002558}
2559
Jim Grosbach3d1eac82011-08-26 21:43:41 +00002560/// parseITCondCode - Try to parse a condition code for an IT instruction.
2561ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2562parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2563 SMLoc S = Parser.getTok().getLoc();
2564 const AsmToken &Tok = Parser.getTok();
2565 if (!Tok.is(AsmToken::Identifier))
2566 return MatchOperand_NoMatch;
2567 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2568 .Case("eq", ARMCC::EQ)
2569 .Case("ne", ARMCC::NE)
2570 .Case("hs", ARMCC::HS)
2571 .Case("cs", ARMCC::HS)
2572 .Case("lo", ARMCC::LO)
2573 .Case("cc", ARMCC::LO)
2574 .Case("mi", ARMCC::MI)
2575 .Case("pl", ARMCC::PL)
2576 .Case("vs", ARMCC::VS)
2577 .Case("vc", ARMCC::VC)
2578 .Case("hi", ARMCC::HI)
2579 .Case("ls", ARMCC::LS)
2580 .Case("ge", ARMCC::GE)
2581 .Case("lt", ARMCC::LT)
2582 .Case("gt", ARMCC::GT)
2583 .Case("le", ARMCC::LE)
2584 .Case("al", ARMCC::AL)
2585 .Default(~0U);
2586 if (CC == ~0U)
2587 return MatchOperand_NoMatch;
2588 Parser.Lex(); // Eat the token.
2589
2590 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2591
2592 return MatchOperand_Success;
2593}
2594
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002595/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002596/// token must be an Identifier when called, and if it is a coprocessor
2597/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002598ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002599parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002600 SMLoc S = Parser.getTok().getLoc();
2601 const AsmToken &Tok = Parser.getTok();
Jim Grosbach54a20ed2011-10-12 20:54:17 +00002602 if (Tok.isNot(AsmToken::Identifier))
2603 return MatchOperand_NoMatch;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002604
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002605 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002606 if (Num == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002607 return MatchOperand_NoMatch;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002608
2609 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002610 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002611 return MatchOperand_Success;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002612}
2613
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002614/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002615/// token must be an Identifier when called, and if it is a coprocessor
2616/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002617ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002618parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002619 SMLoc S = Parser.getTok().getLoc();
2620 const AsmToken &Tok = Parser.getTok();
Jim Grosbach54a20ed2011-10-12 20:54:17 +00002621 if (Tok.isNot(AsmToken::Identifier))
2622 return MatchOperand_NoMatch;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002623
2624 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2625 if (Reg == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002626 return MatchOperand_NoMatch;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002627
2628 Parser.Lex(); // Eat identifier token.
2629 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002630 return MatchOperand_Success;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002631}
2632
Jim Grosbach48399582011-10-12 17:34:41 +00002633/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2634/// coproc_option : '{' imm0_255 '}'
2635ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2636parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2637 SMLoc S = Parser.getTok().getLoc();
2638
2639 // If this isn't a '{', this isn't a coprocessor immediate operand.
2640 if (Parser.getTok().isNot(AsmToken::LCurly))
2641 return MatchOperand_NoMatch;
2642 Parser.Lex(); // Eat the '{'
2643
2644 const MCExpr *Expr;
2645 SMLoc Loc = Parser.getTok().getLoc();
2646 if (getParser().ParseExpression(Expr)) {
2647 Error(Loc, "illegal expression");
2648 return MatchOperand_ParseFail;
2649 }
2650 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2651 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2652 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2653 return MatchOperand_ParseFail;
2654 }
2655 int Val = CE->getValue();
2656
2657 // Check for and consume the closing '}'
2658 if (Parser.getTok().isNot(AsmToken::RCurly))
2659 return MatchOperand_ParseFail;
2660 SMLoc E = Parser.getTok().getLoc();
2661 Parser.Lex(); // Eat the '}'
2662
2663 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2664 return MatchOperand_Success;
2665}
2666
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002667// For register list parsing, we need to map from raw GPR register numbering
2668// to the enumeration values. The enumeration values aren't sorted by
2669// register number due to our using "sp", "lr" and "pc" as canonical names.
2670static unsigned getNextRegister(unsigned Reg) {
2671 // If this is a GPR, we need to do it manually, otherwise we can rely
2672 // on the sort ordering of the enumeration since the other reg-classes
2673 // are sane.
2674 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2675 return Reg + 1;
2676 switch(Reg) {
2677 default: assert(0 && "Invalid GPR number!");
2678 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2679 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2680 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2681 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2682 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2683 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2684 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2685 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2686 }
2687}
2688
Jim Grosbach85a23432011-11-11 21:27:40 +00002689// Return the low-subreg of a given Q register.
2690static unsigned getDRegFromQReg(unsigned QReg) {
2691 switch (QReg) {
2692 default: llvm_unreachable("expected a Q register!");
2693 case ARM::Q0: return ARM::D0;
2694 case ARM::Q1: return ARM::D2;
2695 case ARM::Q2: return ARM::D4;
2696 case ARM::Q3: return ARM::D6;
2697 case ARM::Q4: return ARM::D8;
2698 case ARM::Q5: return ARM::D10;
2699 case ARM::Q6: return ARM::D12;
2700 case ARM::Q7: return ARM::D14;
2701 case ARM::Q8: return ARM::D16;
Jim Grosbacha92a5d82011-11-15 21:01:30 +00002702 case ARM::Q9: return ARM::D18;
Jim Grosbach85a23432011-11-11 21:27:40 +00002703 case ARM::Q10: return ARM::D20;
2704 case ARM::Q11: return ARM::D22;
2705 case ARM::Q12: return ARM::D24;
2706 case ARM::Q13: return ARM::D26;
2707 case ARM::Q14: return ARM::D28;
2708 case ARM::Q15: return ARM::D30;
2709 }
2710}
2711
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002712/// Parse a register list.
Bill Wendling2063b842010-11-18 23:43:05 +00002713bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002714parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan936b0d32010-01-19 21:44:56 +00002715 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00002716 "Token is not a Left Curly Brace");
Bill Wendlinge18980a2010-11-06 22:36:58 +00002717 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002718 Parser.Lex(); // Eat '{' token.
2719 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbya2b99102009-10-09 21:12:28 +00002720
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002721 // Check the first register in the list to see what register class
2722 // this is a list of.
2723 int Reg = tryParseRegister();
2724 if (Reg == -1)
2725 return Error(RegLoc, "register expected");
2726
Jim Grosbach85a23432011-11-11 21:27:40 +00002727 // The reglist instructions have at most 16 registers, so reserve
2728 // space for that many.
2729 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2730
2731 // Allow Q regs and just interpret them as the two D sub-registers.
2732 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2733 Reg = getDRegFromQReg(Reg);
2734 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2735 ++Reg;
2736 }
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00002737 const MCRegisterClass *RC;
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002738 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2739 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2740 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2741 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2742 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2743 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2744 else
2745 return Error(RegLoc, "invalid register in register list");
2746
Jim Grosbach85a23432011-11-11 21:27:40 +00002747 // Store the register.
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002748 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbya2b99102009-10-09 21:12:28 +00002749
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002750 // This starts immediately after the first register token in the list,
2751 // so we can see either a comma or a minus (range separator) as a legal
2752 // next token.
2753 while (Parser.getTok().is(AsmToken::Comma) ||
2754 Parser.getTok().is(AsmToken::Minus)) {
2755 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache891fe82011-11-15 23:19:15 +00002756 Parser.Lex(); // Eat the minus.
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002757 SMLoc EndLoc = Parser.getTok().getLoc();
2758 int EndReg = tryParseRegister();
2759 if (EndReg == -1)
2760 return Error(EndLoc, "register expected");
Jim Grosbach85a23432011-11-11 21:27:40 +00002761 // Allow Q regs and just interpret them as the two D sub-registers.
2762 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2763 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002764 // If the register is the same as the start reg, there's nothing
2765 // more to do.
2766 if (Reg == EndReg)
2767 continue;
2768 // The register must be in the same register class as the first.
2769 if (!RC->contains(EndReg))
2770 return Error(EndLoc, "invalid register in register list");
2771 // Ranges must go from low to high.
2772 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2773 return Error(EndLoc, "bad range in register list");
Kevin Enderbya2b99102009-10-09 21:12:28 +00002774
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002775 // Add all the registers in the range to the register list.
2776 while (Reg != EndReg) {
2777 Reg = getNextRegister(Reg);
2778 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2779 }
2780 continue;
2781 }
2782 Parser.Lex(); // Eat the comma.
2783 RegLoc = Parser.getTok().getLoc();
2784 int OldReg = Reg;
Jim Grosbach98bc7972011-12-08 21:34:20 +00002785 const AsmToken RegTok = Parser.getTok();
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002786 Reg = tryParseRegister();
2787 if (Reg == -1)
Jim Grosbach3337e392011-09-12 23:36:42 +00002788 return Error(RegLoc, "register expected");
Jim Grosbach85a23432011-11-11 21:27:40 +00002789 // Allow Q regs and just interpret them as the two D sub-registers.
2790 bool isQReg = false;
2791 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2792 Reg = getDRegFromQReg(Reg);
2793 isQReg = true;
2794 }
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002795 // The register must be in the same register class as the first.
2796 if (!RC->contains(Reg))
2797 return Error(RegLoc, "invalid register in register list");
2798 // List must be monotonically increasing.
Jim Grosbach98bc7972011-12-08 21:34:20 +00002799 if (getARMRegisterNumbering(Reg) < getARMRegisterNumbering(OldReg))
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002800 return Error(RegLoc, "register list not in ascending order");
Jim Grosbach98bc7972011-12-08 21:34:20 +00002801 if (getARMRegisterNumbering(Reg) == getARMRegisterNumbering(OldReg)) {
2802 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
2803 ") in register list");
2804 continue;
2805 }
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002806 // VFP register lists must also be contiguous.
2807 // It's OK to use the enumeration values directly here rather, as the
2808 // VFP register classes have the enum sorted properly.
2809 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2810 Reg != OldReg + 1)
2811 return Error(RegLoc, "non-contiguous register range");
2812 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbach85a23432011-11-11 21:27:40 +00002813 if (isQReg)
2814 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge18980a2010-11-06 22:36:58 +00002815 }
2816
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002817 SMLoc E = Parser.getTok().getLoc();
2818 if (Parser.getTok().isNot(AsmToken::RCurly))
2819 return Error(E, "'}' expected");
2820 Parser.Lex(); // Eat '}' token.
2821
Jim Grosbach18bf3632011-12-13 21:48:29 +00002822 // Push the register list operand.
Bill Wendling2063b842010-11-18 23:43:05 +00002823 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
Jim Grosbach18bf3632011-12-13 21:48:29 +00002824
2825 // The ARM system instruction variants for LDM/STM have a '^' token here.
2826 if (Parser.getTok().is(AsmToken::Caret)) {
2827 Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
2828 Parser.Lex(); // Eat '^' token.
2829 }
2830
Bill Wendling2063b842010-11-18 23:43:05 +00002831 return false;
Kevin Enderbya2b99102009-10-09 21:12:28 +00002832}
2833
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002834// Helper function to parse the lane index for vector lists.
2835ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach04945c42011-12-02 00:35:16 +00002836parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2837 Index = 0; // Always return a defined index value.
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002838 if (Parser.getTok().is(AsmToken::LBrac)) {
2839 Parser.Lex(); // Eat the '['.
2840 if (Parser.getTok().is(AsmToken::RBrac)) {
2841 // "Dn[]" is the 'all lanes' syntax.
2842 LaneKind = AllLanes;
2843 Parser.Lex(); // Eat the ']'.
2844 return MatchOperand_Success;
2845 }
Jim Grosbach7de7ab82011-12-21 01:19:23 +00002846 const MCExpr *LaneIndex;
2847 SMLoc Loc = Parser.getTok().getLoc();
2848 if (getParser().ParseExpression(LaneIndex)) {
2849 Error(Loc, "illegal expression");
2850 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00002851 }
Jim Grosbach7de7ab82011-12-21 01:19:23 +00002852 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LaneIndex);
2853 if (!CE) {
2854 Error(Loc, "lane index must be empty or an integer");
2855 return MatchOperand_ParseFail;
2856 }
2857 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2858 Error(Parser.getTok().getLoc(), "']' expected");
2859 return MatchOperand_ParseFail;
2860 }
2861 Parser.Lex(); // Eat the ']'.
2862 int64_t Val = CE->getValue();
2863
2864 // FIXME: Make this range check context sensitive for .8, .16, .32.
2865 if (Val < 0 || Val > 7) {
2866 Error(Parser.getTok().getLoc(), "lane index out of range");
2867 return MatchOperand_ParseFail;
2868 }
2869 Index = Val;
2870 LaneKind = IndexedLane;
2871 return MatchOperand_Success;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002872 }
2873 LaneKind = NoLanes;
2874 return MatchOperand_Success;
2875}
2876
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002877// parse a vector register list
2878ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2879parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002880 VectorLaneTy LaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00002881 unsigned LaneIndex;
Jim Grosbach8d579232011-11-15 21:45:55 +00002882 SMLoc S = Parser.getTok().getLoc();
2883 // As an extension (to match gas), support a plain D register or Q register
2884 // (without encosing curly braces) as a single or double entry list,
2885 // respectively.
2886 if (Parser.getTok().is(AsmToken::Identifier)) {
2887 int Reg = tryParseRegister();
2888 if (Reg == -1)
2889 return MatchOperand_NoMatch;
2890 SMLoc E = Parser.getTok().getLoc();
2891 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach04945c42011-12-02 00:35:16 +00002892 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002893 if (Res != MatchOperand_Success)
2894 return Res;
2895 switch (LaneKind) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002896 case NoLanes:
2897 E = Parser.getTok().getLoc();
Jim Grosbach2f50e922011-12-15 21:44:33 +00002898 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002899 break;
2900 case AllLanes:
2901 E = Parser.getTok().getLoc();
Jim Grosbachc5af54e2011-12-21 00:38:54 +00002902 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false,
2903 S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002904 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00002905 case IndexedLane:
2906 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
Jim Grosbach75e2ab52011-12-20 19:21:26 +00002907 LaneIndex,
2908 false, S, E));
Jim Grosbach04945c42011-12-02 00:35:16 +00002909 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002910 }
Jim Grosbach8d579232011-11-15 21:45:55 +00002911 return MatchOperand_Success;
2912 }
2913 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2914 Reg = getDRegFromQReg(Reg);
Jim Grosbach04945c42011-12-02 00:35:16 +00002915 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002916 if (Res != MatchOperand_Success)
2917 return Res;
2918 switch (LaneKind) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002919 case NoLanes:
2920 E = Parser.getTok().getLoc();
Jim Grosbach2f50e922011-12-15 21:44:33 +00002921 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002922 break;
2923 case AllLanes:
2924 E = Parser.getTok().getLoc();
Jim Grosbachc5af54e2011-12-21 00:38:54 +00002925 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, false,
2926 S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002927 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00002928 case IndexedLane:
2929 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
Jim Grosbach75e2ab52011-12-20 19:21:26 +00002930 LaneIndex,
2931 false, S, E));
Jim Grosbach04945c42011-12-02 00:35:16 +00002932 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002933 }
Jim Grosbach8d579232011-11-15 21:45:55 +00002934 return MatchOperand_Success;
2935 }
2936 Error(S, "vector register expected");
2937 return MatchOperand_ParseFail;
2938 }
2939
2940 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002941 return MatchOperand_NoMatch;
2942
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002943 Parser.Lex(); // Eat '{' token.
2944 SMLoc RegLoc = Parser.getTok().getLoc();
2945
2946 int Reg = tryParseRegister();
2947 if (Reg == -1) {
2948 Error(RegLoc, "register expected");
2949 return MatchOperand_ParseFail;
2950 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002951 unsigned Count = 1;
Jim Grosbachc2f16a32011-12-15 21:54:55 +00002952 int Spacing = 0;
Jim Grosbach080a4992011-10-28 00:06:50 +00002953 unsigned FirstReg = Reg;
2954 // The list is of D registers, but we also allow Q regs and just interpret
2955 // them as the two D sub-registers.
2956 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2957 FirstReg = Reg = getDRegFromQReg(Reg);
Jim Grosbach2f50e922011-12-15 21:44:33 +00002958 Spacing = 1; // double-spacing requires explicit D registers, otherwise
2959 // it's ambiguous with four-register single spaced.
Jim Grosbach080a4992011-10-28 00:06:50 +00002960 ++Reg;
2961 ++Count;
2962 }
Jim Grosbach04945c42011-12-02 00:35:16 +00002963 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002964 return MatchOperand_ParseFail;
Jim Grosbach080a4992011-10-28 00:06:50 +00002965
Jim Grosbache891fe82011-11-15 23:19:15 +00002966 while (Parser.getTok().is(AsmToken::Comma) ||
2967 Parser.getTok().is(AsmToken::Minus)) {
2968 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbach2f50e922011-12-15 21:44:33 +00002969 if (!Spacing)
2970 Spacing = 1; // Register range implies a single spaced list.
2971 else if (Spacing == 2) {
2972 Error(Parser.getTok().getLoc(),
2973 "sequential registers in double spaced list");
2974 return MatchOperand_ParseFail;
2975 }
Jim Grosbache891fe82011-11-15 23:19:15 +00002976 Parser.Lex(); // Eat the minus.
2977 SMLoc EndLoc = Parser.getTok().getLoc();
2978 int EndReg = tryParseRegister();
2979 if (EndReg == -1) {
2980 Error(EndLoc, "register expected");
2981 return MatchOperand_ParseFail;
2982 }
2983 // Allow Q regs and just interpret them as the two D sub-registers.
2984 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2985 EndReg = getDRegFromQReg(EndReg) + 1;
2986 // If the register is the same as the start reg, there's nothing
2987 // more to do.
2988 if (Reg == EndReg)
2989 continue;
2990 // The register must be in the same register class as the first.
2991 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
2992 Error(EndLoc, "invalid register in register list");
2993 return MatchOperand_ParseFail;
2994 }
2995 // Ranges must go from low to high.
2996 if (Reg > EndReg) {
2997 Error(EndLoc, "bad range in register list");
2998 return MatchOperand_ParseFail;
2999 }
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003000 // Parse the lane specifier if present.
3001 VectorLaneTy NextLaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00003002 unsigned NextLaneIndex;
3003 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003004 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00003005 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003006 Error(EndLoc, "mismatched lane index in register list");
3007 return MatchOperand_ParseFail;
3008 }
3009 EndLoc = Parser.getTok().getLoc();
Jim Grosbache891fe82011-11-15 23:19:15 +00003010
3011 // Add all the registers in the range to the register list.
3012 Count += EndReg - Reg;
3013 Reg = EndReg;
3014 continue;
3015 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003016 Parser.Lex(); // Eat the comma.
3017 RegLoc = Parser.getTok().getLoc();
3018 int OldReg = Reg;
3019 Reg = tryParseRegister();
3020 if (Reg == -1) {
3021 Error(RegLoc, "register expected");
3022 return MatchOperand_ParseFail;
3023 }
Jim Grosbach080a4992011-10-28 00:06:50 +00003024 // vector register lists must be contiguous.
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003025 // It's OK to use the enumeration values directly here rather, as the
3026 // VFP register classes have the enum sorted properly.
Jim Grosbach080a4992011-10-28 00:06:50 +00003027 //
3028 // The list is of D registers, but we also allow Q regs and just interpret
3029 // them as the two D sub-registers.
3030 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
Jim Grosbach2f50e922011-12-15 21:44:33 +00003031 if (!Spacing)
3032 Spacing = 1; // Register range implies a single spaced list.
3033 else if (Spacing == 2) {
3034 Error(RegLoc,
3035 "invalid register in double-spaced list (must be 'D' register')");
3036 return MatchOperand_ParseFail;
3037 }
Jim Grosbach080a4992011-10-28 00:06:50 +00003038 Reg = getDRegFromQReg(Reg);
3039 if (Reg != OldReg + 1) {
3040 Error(RegLoc, "non-contiguous register range");
3041 return MatchOperand_ParseFail;
3042 }
3043 ++Reg;
3044 Count += 2;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003045 // Parse the lane specifier if present.
3046 VectorLaneTy NextLaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00003047 unsigned NextLaneIndex;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003048 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach04945c42011-12-02 00:35:16 +00003049 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003050 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00003051 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003052 Error(EndLoc, "mismatched lane index in register list");
3053 return MatchOperand_ParseFail;
3054 }
Jim Grosbach080a4992011-10-28 00:06:50 +00003055 continue;
3056 }
Jim Grosbach2f50e922011-12-15 21:44:33 +00003057 // Normal D register.
3058 // Figure out the register spacing (single or double) of the list if
3059 // we don't know it already.
3060 if (!Spacing)
3061 Spacing = 1 + (Reg == OldReg + 2);
3062
3063 // Just check that it's contiguous and keep going.
3064 if (Reg != OldReg + Spacing) {
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003065 Error(RegLoc, "non-contiguous register range");
3066 return MatchOperand_ParseFail;
3067 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003068 ++Count;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003069 // Parse the lane specifier if present.
3070 VectorLaneTy NextLaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00003071 unsigned NextLaneIndex;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003072 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach04945c42011-12-02 00:35:16 +00003073 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003074 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00003075 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003076 Error(EndLoc, "mismatched lane index in register list");
3077 return MatchOperand_ParseFail;
3078 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003079 }
3080
3081 SMLoc E = Parser.getTok().getLoc();
3082 if (Parser.getTok().isNot(AsmToken::RCurly)) {
3083 Error(E, "'}' expected");
3084 return MatchOperand_ParseFail;
3085 }
3086 Parser.Lex(); // Eat '}' token.
3087
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003088 switch (LaneKind) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003089 case NoLanes:
Jim Grosbach2f50e922011-12-15 21:44:33 +00003090 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count,
3091 (Spacing == 2), S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003092 break;
3093 case AllLanes:
3094 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
Jim Grosbachc5af54e2011-12-21 00:38:54 +00003095 (Spacing == 2),
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003096 S, E));
3097 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00003098 case IndexedLane:
3099 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
Jim Grosbach75e2ab52011-12-20 19:21:26 +00003100 LaneIndex,
3101 (Spacing == 2),
3102 S, E));
Jim Grosbach04945c42011-12-02 00:35:16 +00003103 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003104 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003105 return MatchOperand_Success;
3106}
3107
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003108/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbach861e49c2011-02-12 01:34:40 +00003109ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003110parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003111 SMLoc S = Parser.getTok().getLoc();
3112 const AsmToken &Tok = Parser.getTok();
3113 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3114 StringRef OptStr = Tok.getString();
3115
3116 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
3117 .Case("sy", ARM_MB::SY)
3118 .Case("st", ARM_MB::ST)
Jim Grosbach44c3f082011-07-13 23:40:38 +00003119 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003120 .Case("ish", ARM_MB::ISH)
Jim Grosbach44c3f082011-07-13 23:40:38 +00003121 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003122 .Case("ishst", ARM_MB::ISHST)
3123 .Case("nsh", ARM_MB::NSH)
Jim Grosbach44c3f082011-07-13 23:40:38 +00003124 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003125 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach44c3f082011-07-13 23:40:38 +00003126 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003127 .Case("osh", ARM_MB::OSH)
3128 .Case("oshst", ARM_MB::OSHST)
3129 .Default(~0U);
3130
3131 if (Opt == ~0U)
Jim Grosbach861e49c2011-02-12 01:34:40 +00003132 return MatchOperand_NoMatch;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003133
3134 Parser.Lex(); // Eat identifier token.
3135 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00003136 return MatchOperand_Success;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003137}
3138
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003139/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003140ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003141parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003142 SMLoc S = Parser.getTok().getLoc();
3143 const AsmToken &Tok = Parser.getTok();
3144 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3145 StringRef IFlagsStr = Tok.getString();
3146
Owen Anderson10c5b122011-10-05 17:16:40 +00003147 // An iflags string of "none" is interpreted to mean that none of the AIF
3148 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003149 unsigned IFlags = 0;
Owen Anderson10c5b122011-10-05 17:16:40 +00003150 if (IFlagsStr != "none") {
3151 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
3152 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
3153 .Case("a", ARM_PROC::A)
3154 .Case("i", ARM_PROC::I)
3155 .Case("f", ARM_PROC::F)
3156 .Default(~0U);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003157
Owen Anderson10c5b122011-10-05 17:16:40 +00003158 // If some specific iflag is already set, it means that some letter is
3159 // present more than once, this is not acceptable.
3160 if (Flag == ~0U || (IFlags & Flag))
3161 return MatchOperand_NoMatch;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003162
Owen Anderson10c5b122011-10-05 17:16:40 +00003163 IFlags |= Flag;
3164 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003165 }
3166
3167 Parser.Lex(); // Eat identifier token.
3168 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
3169 return MatchOperand_Success;
3170}
3171
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003172/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003173ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003174parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003175 SMLoc S = Parser.getTok().getLoc();
3176 const AsmToken &Tok = Parser.getTok();
3177 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3178 StringRef Mask = Tok.getString();
3179
James Molloy21efa7d2011-09-28 14:21:38 +00003180 if (isMClass()) {
3181 // See ARMv6-M 10.1.1
3182 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
3183 .Case("apsr", 0)
3184 .Case("iapsr", 1)
3185 .Case("eapsr", 2)
3186 .Case("xpsr", 3)
3187 .Case("ipsr", 5)
3188 .Case("epsr", 6)
3189 .Case("iepsr", 7)
3190 .Case("msp", 8)
3191 .Case("psp", 9)
3192 .Case("primask", 16)
3193 .Case("basepri", 17)
3194 .Case("basepri_max", 18)
3195 .Case("faultmask", 19)
3196 .Case("control", 20)
3197 .Default(~0U);
Jim Grosbach3794d822011-12-22 17:17:10 +00003198
James Molloy21efa7d2011-09-28 14:21:38 +00003199 if (FlagsVal == ~0U)
3200 return MatchOperand_NoMatch;
3201
3202 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
3203 // basepri, basepri_max and faultmask only valid for V7m.
3204 return MatchOperand_NoMatch;
Jim Grosbach3794d822011-12-22 17:17:10 +00003205
James Molloy21efa7d2011-09-28 14:21:38 +00003206 Parser.Lex(); // Eat identifier token.
3207 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3208 return MatchOperand_Success;
3209 }
3210
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003211 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
3212 size_t Start = 0, Next = Mask.find('_');
3213 StringRef Flags = "";
Benjamin Kramer20baffb2011-11-06 20:37:06 +00003214 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003215 if (Next != StringRef::npos)
3216 Flags = Mask.slice(Next+1, Mask.size());
3217
3218 // FlagsVal contains the complete mask:
3219 // 3-0: Mask
3220 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3221 unsigned FlagsVal = 0;
3222
3223 if (SpecReg == "apsr") {
3224 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachd25c2cd2011-07-19 22:45:10 +00003225 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003226 .Case("g", 0x4) // same as CPSR_s
3227 .Case("nzcvqg", 0xc) // same as CPSR_fs
3228 .Default(~0U);
3229
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00003230 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003231 if (!Flags.empty())
3232 return MatchOperand_NoMatch;
3233 else
Jim Grosbach0ecd3952011-09-14 20:03:46 +00003234 FlagsVal = 8; // No flag
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00003235 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003236 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes54452132011-05-25 00:35:03 +00003237 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
3238 Flags = "fc";
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003239 for (int i = 0, e = Flags.size(); i != e; ++i) {
3240 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
3241 .Case("c", 1)
3242 .Case("x", 2)
3243 .Case("s", 4)
3244 .Case("f", 8)
3245 .Default(~0U);
3246
3247 // If some specific flag is already set, it means that some letter is
3248 // present more than once, this is not acceptable.
3249 if (FlagsVal == ~0U || (FlagsVal & Flag))
3250 return MatchOperand_NoMatch;
3251 FlagsVal |= Flag;
3252 }
3253 } else // No match for special register.
3254 return MatchOperand_NoMatch;
3255
Owen Anderson03a173e2011-10-21 18:43:28 +00003256 // Special register without flags is NOT equivalent to "fc" flags.
3257 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3258 // two lines would enable gas compatibility at the expense of breaking
3259 // round-tripping.
3260 //
3261 // if (!FlagsVal)
3262 // FlagsVal = 0x9;
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003263
3264 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3265 if (SpecReg == "spsr")
3266 FlagsVal |= 16;
3267
3268 Parser.Lex(); // Eat identifier token.
3269 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3270 return MatchOperand_Success;
3271}
3272
Jim Grosbach27c1e252011-07-21 17:23:04 +00003273ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3274parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3275 int Low, int High) {
3276 const AsmToken &Tok = Parser.getTok();
3277 if (Tok.isNot(AsmToken::Identifier)) {
3278 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3279 return MatchOperand_ParseFail;
3280 }
3281 StringRef ShiftName = Tok.getString();
Benjamin Kramer20baffb2011-11-06 20:37:06 +00003282 std::string LowerOp = Op.lower();
3283 std::string UpperOp = Op.upper();
Jim Grosbach27c1e252011-07-21 17:23:04 +00003284 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3285 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3286 return MatchOperand_ParseFail;
3287 }
3288 Parser.Lex(); // Eat shift type token.
3289
3290 // There must be a '#' and a shift amount.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003291 if (Parser.getTok().isNot(AsmToken::Hash) &&
3292 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach27c1e252011-07-21 17:23:04 +00003293 Error(Parser.getTok().getLoc(), "'#' expected");
3294 return MatchOperand_ParseFail;
3295 }
3296 Parser.Lex(); // Eat hash token.
3297
3298 const MCExpr *ShiftAmount;
3299 SMLoc Loc = Parser.getTok().getLoc();
3300 if (getParser().ParseExpression(ShiftAmount)) {
3301 Error(Loc, "illegal expression");
3302 return MatchOperand_ParseFail;
3303 }
3304 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3305 if (!CE) {
3306 Error(Loc, "constant expression expected");
3307 return MatchOperand_ParseFail;
3308 }
3309 int Val = CE->getValue();
3310 if (Val < Low || Val > High) {
3311 Error(Loc, "immediate value out of range");
3312 return MatchOperand_ParseFail;
3313 }
3314
3315 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3316
3317 return MatchOperand_Success;
3318}
3319
Jim Grosbach0a547702011-07-22 17:44:50 +00003320ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3321parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3322 const AsmToken &Tok = Parser.getTok();
3323 SMLoc S = Tok.getLoc();
3324 if (Tok.isNot(AsmToken::Identifier)) {
3325 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3326 return MatchOperand_ParseFail;
3327 }
3328 int Val = StringSwitch<int>(Tok.getString())
3329 .Case("be", 1)
3330 .Case("le", 0)
3331 .Default(-1);
3332 Parser.Lex(); // Eat the token.
3333
3334 if (Val == -1) {
3335 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3336 return MatchOperand_ParseFail;
3337 }
3338 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3339 getContext()),
3340 S, Parser.getTok().getLoc()));
3341 return MatchOperand_Success;
3342}
3343
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00003344/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3345/// instructions. Legal values are:
3346/// lsl #n 'n' in [0,31]
3347/// asr #n 'n' in [1,32]
3348/// n == 32 encoded as n == 0.
3349ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3350parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3351 const AsmToken &Tok = Parser.getTok();
3352 SMLoc S = Tok.getLoc();
3353 if (Tok.isNot(AsmToken::Identifier)) {
3354 Error(S, "shift operator 'asr' or 'lsl' expected");
3355 return MatchOperand_ParseFail;
3356 }
3357 StringRef ShiftName = Tok.getString();
3358 bool isASR;
3359 if (ShiftName == "lsl" || ShiftName == "LSL")
3360 isASR = false;
3361 else if (ShiftName == "asr" || ShiftName == "ASR")
3362 isASR = true;
3363 else {
3364 Error(S, "shift operator 'asr' or 'lsl' expected");
3365 return MatchOperand_ParseFail;
3366 }
3367 Parser.Lex(); // Eat the operator.
3368
3369 // A '#' and a shift amount.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003370 if (Parser.getTok().isNot(AsmToken::Hash) &&
3371 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00003372 Error(Parser.getTok().getLoc(), "'#' expected");
3373 return MatchOperand_ParseFail;
3374 }
3375 Parser.Lex(); // Eat hash token.
3376
3377 const MCExpr *ShiftAmount;
3378 SMLoc E = Parser.getTok().getLoc();
3379 if (getParser().ParseExpression(ShiftAmount)) {
3380 Error(E, "malformed shift expression");
3381 return MatchOperand_ParseFail;
3382 }
3383 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3384 if (!CE) {
3385 Error(E, "shift amount must be an immediate");
3386 return MatchOperand_ParseFail;
3387 }
3388
3389 int64_t Val = CE->getValue();
3390 if (isASR) {
3391 // Shift amount must be in [1,32]
3392 if (Val < 1 || Val > 32) {
3393 Error(E, "'asr' shift amount must be in range [1,32]");
3394 return MatchOperand_ParseFail;
3395 }
Owen Andersonf01e2de2011-09-26 21:06:22 +00003396 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3397 if (isThumb() && Val == 32) {
3398 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3399 return MatchOperand_ParseFail;
3400 }
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00003401 if (Val == 32) Val = 0;
3402 } else {
3403 // Shift amount must be in [1,32]
3404 if (Val < 0 || Val > 31) {
3405 Error(E, "'lsr' shift amount must be in range [0,31]");
3406 return MatchOperand_ParseFail;
3407 }
3408 }
3409
3410 E = Parser.getTok().getLoc();
3411 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3412
3413 return MatchOperand_Success;
3414}
3415
Jim Grosbach833b9d32011-07-27 20:15:40 +00003416/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3417/// of instructions. Legal values are:
3418/// ror #n 'n' in {0, 8, 16, 24}
3419ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3420parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3421 const AsmToken &Tok = Parser.getTok();
3422 SMLoc S = Tok.getLoc();
Jim Grosbach82213192011-09-19 20:29:33 +00003423 if (Tok.isNot(AsmToken::Identifier))
3424 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00003425 StringRef ShiftName = Tok.getString();
Jim Grosbach82213192011-09-19 20:29:33 +00003426 if (ShiftName != "ror" && ShiftName != "ROR")
3427 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00003428 Parser.Lex(); // Eat the operator.
3429
3430 // A '#' and a rotate amount.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003431 if (Parser.getTok().isNot(AsmToken::Hash) &&
3432 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach833b9d32011-07-27 20:15:40 +00003433 Error(Parser.getTok().getLoc(), "'#' expected");
3434 return MatchOperand_ParseFail;
3435 }
3436 Parser.Lex(); // Eat hash token.
3437
3438 const MCExpr *ShiftAmount;
3439 SMLoc E = Parser.getTok().getLoc();
3440 if (getParser().ParseExpression(ShiftAmount)) {
3441 Error(E, "malformed rotate expression");
3442 return MatchOperand_ParseFail;
3443 }
3444 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3445 if (!CE) {
3446 Error(E, "rotate amount must be an immediate");
3447 return MatchOperand_ParseFail;
3448 }
3449
3450 int64_t Val = CE->getValue();
3451 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3452 // normally, zero is represented in asm by omitting the rotate operand
3453 // entirely.
3454 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3455 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3456 return MatchOperand_ParseFail;
3457 }
3458
3459 E = Parser.getTok().getLoc();
3460 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3461
3462 return MatchOperand_Success;
3463}
3464
Jim Grosbach864b6092011-07-28 21:34:26 +00003465ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3466parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3467 SMLoc S = Parser.getTok().getLoc();
3468 // The bitfield descriptor is really two operands, the LSB and the width.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003469 if (Parser.getTok().isNot(AsmToken::Hash) &&
3470 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach864b6092011-07-28 21:34:26 +00003471 Error(Parser.getTok().getLoc(), "'#' expected");
3472 return MatchOperand_ParseFail;
3473 }
3474 Parser.Lex(); // Eat hash token.
3475
3476 const MCExpr *LSBExpr;
3477 SMLoc E = Parser.getTok().getLoc();
3478 if (getParser().ParseExpression(LSBExpr)) {
3479 Error(E, "malformed immediate expression");
3480 return MatchOperand_ParseFail;
3481 }
3482 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3483 if (!CE) {
3484 Error(E, "'lsb' operand must be an immediate");
3485 return MatchOperand_ParseFail;
3486 }
3487
3488 int64_t LSB = CE->getValue();
3489 // The LSB must be in the range [0,31]
3490 if (LSB < 0 || LSB > 31) {
3491 Error(E, "'lsb' operand must be in the range [0,31]");
3492 return MatchOperand_ParseFail;
3493 }
3494 E = Parser.getTok().getLoc();
3495
3496 // Expect another immediate operand.
3497 if (Parser.getTok().isNot(AsmToken::Comma)) {
3498 Error(Parser.getTok().getLoc(), "too few operands");
3499 return MatchOperand_ParseFail;
3500 }
3501 Parser.Lex(); // Eat hash token.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003502 if (Parser.getTok().isNot(AsmToken::Hash) &&
3503 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach864b6092011-07-28 21:34:26 +00003504 Error(Parser.getTok().getLoc(), "'#' expected");
3505 return MatchOperand_ParseFail;
3506 }
3507 Parser.Lex(); // Eat hash token.
3508
3509 const MCExpr *WidthExpr;
3510 if (getParser().ParseExpression(WidthExpr)) {
3511 Error(E, "malformed immediate expression");
3512 return MatchOperand_ParseFail;
3513 }
3514 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3515 if (!CE) {
3516 Error(E, "'width' operand must be an immediate");
3517 return MatchOperand_ParseFail;
3518 }
3519
3520 int64_t Width = CE->getValue();
3521 // The LSB must be in the range [1,32-lsb]
3522 if (Width < 1 || Width > 32 - LSB) {
3523 Error(E, "'width' operand must be in the range [1,32-lsb]");
3524 return MatchOperand_ParseFail;
3525 }
3526 E = Parser.getTok().getLoc();
3527
3528 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3529
3530 return MatchOperand_Success;
3531}
3532
Jim Grosbachd3595712011-08-03 23:50:40 +00003533ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3534parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3535 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachc320c852011-08-05 21:28:30 +00003536 // postidx_reg := '+' register {, shift}
3537 // | '-' register {, shift}
3538 // | register {, shift}
Jim Grosbachd3595712011-08-03 23:50:40 +00003539
3540 // This method must return MatchOperand_NoMatch without consuming any tokens
3541 // in the case where there is no match, as other alternatives take other
3542 // parse methods.
3543 AsmToken Tok = Parser.getTok();
3544 SMLoc S = Tok.getLoc();
3545 bool haveEaten = false;
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00003546 bool isAdd = true;
Jim Grosbachd3595712011-08-03 23:50:40 +00003547 int Reg = -1;
3548 if (Tok.is(AsmToken::Plus)) {
3549 Parser.Lex(); // Eat the '+' token.
3550 haveEaten = true;
3551 } else if (Tok.is(AsmToken::Minus)) {
3552 Parser.Lex(); // Eat the '-' token.
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00003553 isAdd = false;
Jim Grosbachd3595712011-08-03 23:50:40 +00003554 haveEaten = true;
3555 }
3556 if (Parser.getTok().is(AsmToken::Identifier))
3557 Reg = tryParseRegister();
3558 if (Reg == -1) {
3559 if (!haveEaten)
3560 return MatchOperand_NoMatch;
3561 Error(Parser.getTok().getLoc(), "register expected");
3562 return MatchOperand_ParseFail;
3563 }
3564 SMLoc E = Parser.getTok().getLoc();
3565
Jim Grosbachc320c852011-08-05 21:28:30 +00003566 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3567 unsigned ShiftImm = 0;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00003568 if (Parser.getTok().is(AsmToken::Comma)) {
3569 Parser.Lex(); // Eat the ','.
3570 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3571 return MatchOperand_ParseFail;
3572 }
Jim Grosbachc320c852011-08-05 21:28:30 +00003573
3574 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3575 ShiftImm, S, E));
Jim Grosbachd3595712011-08-03 23:50:40 +00003576
3577 return MatchOperand_Success;
3578}
3579
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00003580ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3581parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3582 // Check for a post-index addressing register operand. Specifically:
3583 // am3offset := '+' register
3584 // | '-' register
3585 // | register
3586 // | # imm
3587 // | # + imm
3588 // | # - imm
3589
3590 // This method must return MatchOperand_NoMatch without consuming any tokens
3591 // in the case where there is no match, as other alternatives take other
3592 // parse methods.
3593 AsmToken Tok = Parser.getTok();
3594 SMLoc S = Tok.getLoc();
3595
3596 // Do immediates first, as we always parse those if we have a '#'.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003597 if (Parser.getTok().is(AsmToken::Hash) ||
3598 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00003599 Parser.Lex(); // Eat the '#'.
3600 // Explicitly look for a '-', as we need to encode negative zero
3601 // differently.
3602 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3603 const MCExpr *Offset;
3604 if (getParser().ParseExpression(Offset))
3605 return MatchOperand_ParseFail;
3606 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3607 if (!CE) {
3608 Error(S, "constant expression expected");
3609 return MatchOperand_ParseFail;
3610 }
3611 SMLoc E = Tok.getLoc();
3612 // Negative zero is encoded as the flag value INT32_MIN.
3613 int32_t Val = CE->getValue();
3614 if (isNegative && Val == 0)
3615 Val = INT32_MIN;
3616
3617 Operands.push_back(
3618 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3619
3620 return MatchOperand_Success;
3621 }
3622
3623
3624 bool haveEaten = false;
3625 bool isAdd = true;
3626 int Reg = -1;
3627 if (Tok.is(AsmToken::Plus)) {
3628 Parser.Lex(); // Eat the '+' token.
3629 haveEaten = true;
3630 } else if (Tok.is(AsmToken::Minus)) {
3631 Parser.Lex(); // Eat the '-' token.
3632 isAdd = false;
3633 haveEaten = true;
3634 }
3635 if (Parser.getTok().is(AsmToken::Identifier))
3636 Reg = tryParseRegister();
3637 if (Reg == -1) {
3638 if (!haveEaten)
3639 return MatchOperand_NoMatch;
3640 Error(Parser.getTok().getLoc(), "register expected");
3641 return MatchOperand_ParseFail;
3642 }
3643 SMLoc E = Parser.getTok().getLoc();
3644
3645 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3646 0, S, E));
3647
3648 return MatchOperand_Success;
3649}
3650
Jim Grosbach7db8d692011-09-08 22:07:06 +00003651/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3652/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3653/// when they refer multiple MIOperands inside a single one.
3654bool ARMAsmParser::
3655cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3656 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3657 // Rt, Rt2
3658 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3659 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3660 // Create a writeback register dummy placeholder.
3661 Inst.addOperand(MCOperand::CreateReg(0));
3662 // addr
3663 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3664 // pred
3665 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3666 return true;
3667}
3668
3669/// cvtT2StrdPre - Convert parsed operands to MCInst.
3670/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3671/// when they refer multiple MIOperands inside a single one.
3672bool ARMAsmParser::
3673cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3674 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3675 // Create a writeback register dummy placeholder.
3676 Inst.addOperand(MCOperand::CreateReg(0));
3677 // Rt, Rt2
3678 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3679 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3680 // addr
3681 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3682 // pred
3683 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3684 return true;
3685}
3686
Jim Grosbachc086f682011-09-08 00:39:19 +00003687/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3688/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3689/// when they refer multiple MIOperands inside a single one.
3690bool ARMAsmParser::
3691cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3692 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3693 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3694
3695 // Create a writeback register dummy placeholder.
3696 Inst.addOperand(MCOperand::CreateImm(0));
3697
3698 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3699 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3700 return true;
3701}
3702
Jim Grosbach9c0b86a2011-09-16 21:55:56 +00003703/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3704/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3705/// when they refer multiple MIOperands inside a single one.
3706bool ARMAsmParser::
3707cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3708 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3709 // Create a writeback register dummy placeholder.
3710 Inst.addOperand(MCOperand::CreateImm(0));
3711 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3712 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3713 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3714 return true;
3715}
3716
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003717/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003718/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3719/// when they refer multiple MIOperands inside a single one.
3720bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003721cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003722 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3723 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3724
3725 // Create a writeback register dummy placeholder.
3726 Inst.addOperand(MCOperand::CreateImm(0));
3727
Jim Grosbachd3595712011-08-03 23:50:40 +00003728 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003729 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3730 return true;
3731}
3732
Owen Anderson16d33f32011-08-26 20:43:14 +00003733/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3734/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3735/// when they refer multiple MIOperands inside a single one.
3736bool ARMAsmParser::
3737cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3738 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3739 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3740
3741 // Create a writeback register dummy placeholder.
3742 Inst.addOperand(MCOperand::CreateImm(0));
3743
3744 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3745 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3746 return true;
3747}
3748
3749
Jim Grosbachd564bf32011-08-11 19:22:40 +00003750/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3751/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3752/// when they refer multiple MIOperands inside a single one.
3753bool ARMAsmParser::
3754cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3755 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3756 // Create a writeback register dummy placeholder.
3757 Inst.addOperand(MCOperand::CreateImm(0));
3758 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3759 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3760 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3761 return true;
3762}
3763
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003764/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003765/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3766/// when they refer multiple MIOperands inside a single one.
3767bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003768cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003769 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3770 // Create a writeback register dummy placeholder.
3771 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd564bf32011-08-11 19:22:40 +00003772 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3773 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3774 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbachd3595712011-08-03 23:50:40 +00003775 return true;
3776}
3777
Jim Grosbachd886f8c2011-08-11 21:17:22 +00003778/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3779/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3780/// when they refer multiple MIOperands inside a single one.
3781bool ARMAsmParser::
3782cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3783 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3784 // Create a writeback register dummy placeholder.
3785 Inst.addOperand(MCOperand::CreateImm(0));
3786 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3787 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3788 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3789 return true;
3790}
3791
Jim Grosbachd3595712011-08-03 23:50:40 +00003792/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3793/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3794/// when they refer multiple MIOperands inside a single one.
3795bool ARMAsmParser::
3796cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3797 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3798 // Rt
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003799 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbachd3595712011-08-03 23:50:40 +00003800 // Create a writeback register dummy placeholder.
3801 Inst.addOperand(MCOperand::CreateImm(0));
3802 // addr
3803 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3804 // offset
3805 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3806 // pred
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003807 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3808 return true;
3809}
3810
Jim Grosbachd3595712011-08-03 23:50:40 +00003811/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003812/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3813/// when they refer multiple MIOperands inside a single one.
3814bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003815cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3816 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3817 // Rt
Owen Andersonb0e68992011-07-28 17:18:57 +00003818 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003819 // Create a writeback register dummy placeholder.
3820 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd3595712011-08-03 23:50:40 +00003821 // addr
3822 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3823 // offset
3824 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3825 // pred
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003826 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3827 return true;
3828}
3829
Jim Grosbachd3595712011-08-03 23:50:40 +00003830/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003831/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3832/// when they refer multiple MIOperands inside a single one.
3833bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003834cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3835 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003836 // Create a writeback register dummy placeholder.
3837 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd3595712011-08-03 23:50:40 +00003838 // Rt
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003839 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbachd3595712011-08-03 23:50:40 +00003840 // addr
3841 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3842 // offset
3843 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3844 // pred
3845 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3846 return true;
3847}
3848
3849/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3850/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3851/// when they refer multiple MIOperands inside a single one.
3852bool ARMAsmParser::
3853cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3854 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3855 // Create a writeback register dummy placeholder.
3856 Inst.addOperand(MCOperand::CreateImm(0));
3857 // Rt
3858 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3859 // addr
3860 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3861 // offset
3862 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3863 // pred
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003864 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3865 return true;
3866}
3867
Jim Grosbach5b96b802011-08-10 20:29:19 +00003868/// cvtLdrdPre - Convert parsed operands to MCInst.
3869/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3870/// when they refer multiple MIOperands inside a single one.
3871bool ARMAsmParser::
3872cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3873 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3874 // Rt, Rt2
3875 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3876 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3877 // Create a writeback register dummy placeholder.
3878 Inst.addOperand(MCOperand::CreateImm(0));
3879 // addr
3880 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3881 // pred
3882 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3883 return true;
3884}
3885
Jim Grosbacheb09f492011-08-11 20:28:23 +00003886/// cvtStrdPre - Convert parsed operands to MCInst.
3887/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3888/// when they refer multiple MIOperands inside a single one.
3889bool ARMAsmParser::
3890cvtStrdPre(MCInst &Inst, unsigned Opcode,
3891 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3892 // Create a writeback register dummy placeholder.
3893 Inst.addOperand(MCOperand::CreateImm(0));
3894 // Rt, Rt2
3895 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3896 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3897 // addr
3898 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3899 // pred
3900 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3901 return true;
3902}
3903
Jim Grosbachcd4dd252011-08-10 22:42:16 +00003904/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3905/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3906/// when they refer multiple MIOperands inside a single one.
3907bool ARMAsmParser::
3908cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3909 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3910 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3911 // Create a writeback register dummy placeholder.
3912 Inst.addOperand(MCOperand::CreateImm(0));
3913 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3914 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3915 return true;
3916}
3917
Jim Grosbach8e048492011-08-19 22:07:46 +00003918/// cvtThumbMultiple- Convert parsed operands to MCInst.
3919/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3920/// when they refer multiple MIOperands inside a single one.
3921bool ARMAsmParser::
3922cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3923 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3924 // The second source operand must be the same register as the destination
3925 // operand.
3926 if (Operands.size() == 6 &&
Jim Grosbach459422d2011-08-19 22:30:46 +00003927 (((ARMOperand*)Operands[3])->getReg() !=
3928 ((ARMOperand*)Operands[5])->getReg()) &&
3929 (((ARMOperand*)Operands[3])->getReg() !=
3930 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach8e048492011-08-19 22:07:46 +00003931 Error(Operands[3]->getStartLoc(),
Jim Grosbach459422d2011-08-19 22:30:46 +00003932 "destination register must match source register");
Jim Grosbach8e048492011-08-19 22:07:46 +00003933 return false;
3934 }
3935 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3936 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach5a5ce632011-11-10 22:10:12 +00003937 // If we have a three-operand form, make sure to set Rn to be the operand
3938 // that isn't the same as Rd.
3939 unsigned RegOp = 4;
3940 if (Operands.size() == 6 &&
3941 ((ARMOperand*)Operands[4])->getReg() ==
3942 ((ARMOperand*)Operands[3])->getReg())
3943 RegOp = 5;
3944 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
3945 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach8e048492011-08-19 22:07:46 +00003946 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3947
3948 return true;
3949}
Jim Grosbachcd4dd252011-08-10 22:42:16 +00003950
Jim Grosbach3ea06572011-10-24 22:16:58 +00003951bool ARMAsmParser::
3952cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3953 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3954 // Vd
Jim Grosbach182b6a02011-11-29 23:51:09 +00003955 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach3ea06572011-10-24 22:16:58 +00003956 // Create a writeback register dummy placeholder.
3957 Inst.addOperand(MCOperand::CreateImm(0));
3958 // Vn
3959 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3960 // pred
3961 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3962 return true;
3963}
3964
3965bool ARMAsmParser::
3966cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3967 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3968 // Vd
Jim Grosbach182b6a02011-11-29 23:51:09 +00003969 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach3ea06572011-10-24 22:16:58 +00003970 // Create a writeback register dummy placeholder.
3971 Inst.addOperand(MCOperand::CreateImm(0));
3972 // Vn
3973 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3974 // Vm
3975 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3976 // pred
3977 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3978 return true;
3979}
3980
Jim Grosbach05df4602011-10-31 21:50:31 +00003981bool ARMAsmParser::
3982cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
3983 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3984 // Create a writeback register dummy placeholder.
3985 Inst.addOperand(MCOperand::CreateImm(0));
3986 // Vn
3987 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3988 // Vt
Jim Grosbach182b6a02011-11-29 23:51:09 +00003989 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach05df4602011-10-31 21:50:31 +00003990 // pred
3991 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3992 return true;
3993}
3994
3995bool ARMAsmParser::
3996cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
3997 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3998 // Create a writeback register dummy placeholder.
3999 Inst.addOperand(MCOperand::CreateImm(0));
4000 // Vn
4001 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4002 // Vm
4003 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4004 // Vt
Jim Grosbach182b6a02011-11-29 23:51:09 +00004005 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach05df4602011-10-31 21:50:31 +00004006 // pred
4007 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4008 return true;
4009}
4010
Bill Wendlinge18980a2010-11-06 22:36:58 +00004011/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004012/// or an error. The first token must be a '[' when called.
Bill Wendling2063b842010-11-18 23:43:05 +00004013bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00004014parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004015 SMLoc S, E;
Sean Callanan936b0d32010-01-19 21:44:56 +00004016 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00004017 "Token is not a Left Bracket");
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004018 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00004019 Parser.Lex(); // Eat left bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004020
Sean Callanan936b0d32010-01-19 21:44:56 +00004021 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004022 int BaseRegNum = tryParseRegister();
Jim Grosbachd3595712011-08-03 23:50:40 +00004023 if (BaseRegNum == -1)
4024 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004025
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00004026 // The next token must either be a comma or a closing bracket.
4027 const AsmToken &Tok = Parser.getTok();
4028 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbachd3595712011-08-03 23:50:40 +00004029 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00004030
Jim Grosbachd3595712011-08-03 23:50:40 +00004031 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004032 E = Tok.getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00004033 Parser.Lex(); // Eat right bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004034
Jim Grosbachd3595712011-08-03 23:50:40 +00004035 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbacha95ec992011-10-11 17:29:55 +00004036 0, 0, false, S, E));
Jim Grosbach32ff5582010-11-29 23:18:01 +00004037
Jim Grosbach40700e02011-09-19 18:42:21 +00004038 // If there's a pre-indexing writeback marker, '!', just add it as a token
4039 // operand. It's rather odd, but syntactically valid.
4040 if (Parser.getTok().is(AsmToken::Exclaim)) {
4041 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4042 Parser.Lex(); // Eat the '!'.
4043 }
4044
Jim Grosbachd3595712011-08-03 23:50:40 +00004045 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004046 }
Daniel Dunbarf5164f42011-01-18 05:34:24 +00004047
Jim Grosbachd3595712011-08-03 23:50:40 +00004048 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
4049 Parser.Lex(); // Eat the comma.
Daniel Dunbarf5164f42011-01-18 05:34:24 +00004050
Jim Grosbacha95ec992011-10-11 17:29:55 +00004051 // If we have a ':', it's an alignment specifier.
4052 if (Parser.getTok().is(AsmToken::Colon)) {
4053 Parser.Lex(); // Eat the ':'.
4054 E = Parser.getTok().getLoc();
4055
4056 const MCExpr *Expr;
4057 if (getParser().ParseExpression(Expr))
4058 return true;
4059
4060 // The expression has to be a constant. Memory references with relocations
4061 // don't come through here, as they use the <label> forms of the relevant
4062 // instructions.
4063 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4064 if (!CE)
4065 return Error (E, "constant expression expected");
4066
4067 unsigned Align = 0;
4068 switch (CE->getValue()) {
4069 default:
Jim Grosbachcef98cd2011-12-19 18:31:43 +00004070 return Error(E,
4071 "alignment specifier must be 16, 32, 64, 128, or 256 bits");
4072 case 16: Align = 2; break;
4073 case 32: Align = 4; break;
Jim Grosbacha95ec992011-10-11 17:29:55 +00004074 case 64: Align = 8; break;
4075 case 128: Align = 16; break;
4076 case 256: Align = 32; break;
4077 }
4078
4079 // Now we should have the closing ']'
4080 E = Parser.getTok().getLoc();
4081 if (Parser.getTok().isNot(AsmToken::RBrac))
4082 return Error(E, "']' expected");
4083 Parser.Lex(); // Eat right bracket token.
4084
4085 // Don't worry about range checking the value here. That's handled by
4086 // the is*() predicates.
4087 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
4088 ARM_AM::no_shift, 0, Align,
4089 false, S, E));
4090
4091 // If there's a pre-indexing writeback marker, '!', just add it as a token
4092 // operand.
4093 if (Parser.getTok().is(AsmToken::Exclaim)) {
4094 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4095 Parser.Lex(); // Eat the '!'.
4096 }
4097
4098 return false;
4099 }
4100
4101 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach8279c182011-11-15 22:14:41 +00004102 // offset. Be friendly and also accept a plain integer (without a leading
4103 // hash) for gas compatibility.
4104 if (Parser.getTok().is(AsmToken::Hash) ||
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004105 Parser.getTok().is(AsmToken::Dollar) ||
Jim Grosbach8279c182011-11-15 22:14:41 +00004106 Parser.getTok().is(AsmToken::Integer)) {
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004107 if (Parser.getTok().isNot(AsmToken::Integer))
Jim Grosbach8279c182011-11-15 22:14:41 +00004108 Parser.Lex(); // Eat the '#'.
Jim Grosbachd3595712011-08-03 23:50:40 +00004109 E = Parser.getTok().getLoc();
Daniel Dunbarf5164f42011-01-18 05:34:24 +00004110
Owen Anderson967674d2011-08-29 19:36:44 +00004111 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbachd3595712011-08-03 23:50:40 +00004112 const MCExpr *Offset;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004113 if (getParser().ParseExpression(Offset))
4114 return true;
Jim Grosbachd3595712011-08-03 23:50:40 +00004115
4116 // The expression has to be a constant. Memory references with relocations
4117 // don't come through here, as they use the <label> forms of the relevant
4118 // instructions.
4119 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
4120 if (!CE)
4121 return Error (E, "constant expression expected");
4122
Owen Anderson967674d2011-08-29 19:36:44 +00004123 // If the constant was #-0, represent it as INT32_MIN.
4124 int32_t Val = CE->getValue();
4125 if (isNegative && Val == 0)
4126 CE = MCConstantExpr::Create(INT32_MIN, getContext());
4127
Jim Grosbachd3595712011-08-03 23:50:40 +00004128 // Now we should have the closing ']'
4129 E = Parser.getTok().getLoc();
4130 if (Parser.getTok().isNot(AsmToken::RBrac))
4131 return Error(E, "']' expected");
4132 Parser.Lex(); // Eat right bracket token.
4133
4134 // Don't worry about range checking the value here. That's handled by
4135 // the is*() predicates.
4136 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbacha95ec992011-10-11 17:29:55 +00004137 ARM_AM::no_shift, 0, 0,
4138 false, S, E));
Jim Grosbachd3595712011-08-03 23:50:40 +00004139
4140 // If there's a pre-indexing writeback marker, '!', just add it as a token
4141 // operand.
4142 if (Parser.getTok().is(AsmToken::Exclaim)) {
4143 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4144 Parser.Lex(); // Eat the '!'.
4145 }
4146
4147 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004148 }
Jim Grosbachd3595712011-08-03 23:50:40 +00004149
4150 // The register offset is optionally preceded by a '+' or '-'
4151 bool isNegative = false;
4152 if (Parser.getTok().is(AsmToken::Minus)) {
4153 isNegative = true;
4154 Parser.Lex(); // Eat the '-'.
4155 } else if (Parser.getTok().is(AsmToken::Plus)) {
4156 // Nothing to do.
4157 Parser.Lex(); // Eat the '+'.
4158 }
4159
4160 E = Parser.getTok().getLoc();
4161 int OffsetRegNum = tryParseRegister();
4162 if (OffsetRegNum == -1)
4163 return Error(E, "register expected");
4164
4165 // If there's a shift operator, handle it.
4166 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00004167 unsigned ShiftImm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00004168 if (Parser.getTok().is(AsmToken::Comma)) {
4169 Parser.Lex(); // Eat the ','.
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00004170 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbachd3595712011-08-03 23:50:40 +00004171 return true;
4172 }
4173
4174 // Now we should have the closing ']'
4175 E = Parser.getTok().getLoc();
4176 if (Parser.getTok().isNot(AsmToken::RBrac))
4177 return Error(E, "']' expected");
4178 Parser.Lex(); // Eat right bracket token.
4179
4180 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbacha95ec992011-10-11 17:29:55 +00004181 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbachd3595712011-08-03 23:50:40 +00004182 S, E));
4183
Jim Grosbachc320c852011-08-05 21:28:30 +00004184 // If there's a pre-indexing writeback marker, '!', just add it as a token
4185 // operand.
4186 if (Parser.getTok().is(AsmToken::Exclaim)) {
4187 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4188 Parser.Lex(); // Eat the '!'.
4189 }
Jim Grosbachd3595712011-08-03 23:50:40 +00004190
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004191 return false;
4192}
4193
Jim Grosbachd3595712011-08-03 23:50:40 +00004194/// parseMemRegOffsetShift - one of these two:
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004195/// ( lsl | lsr | asr | ror ) , # shift_amount
4196/// rrx
Jim Grosbachd3595712011-08-03 23:50:40 +00004197/// return true if it parses a shift otherwise it returns false.
4198bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
4199 unsigned &Amount) {
4200 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan936b0d32010-01-19 21:44:56 +00004201 const AsmToken &Tok = Parser.getTok();
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004202 if (Tok.isNot(AsmToken::Identifier))
4203 return true;
Benjamin Kramer92d89982010-07-14 22:38:02 +00004204 StringRef ShiftName = Tok.getString();
Jim Grosbach3b559ff2011-12-07 23:40:58 +00004205 if (ShiftName == "lsl" || ShiftName == "LSL" ||
4206 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004207 St = ARM_AM::lsl;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004208 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004209 St = ARM_AM::lsr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004210 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004211 St = ARM_AM::asr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004212 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004213 St = ARM_AM::ror;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004214 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004215 St = ARM_AM::rrx;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004216 else
Jim Grosbachd3595712011-08-03 23:50:40 +00004217 return Error(Loc, "illegal shift operator");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004218 Parser.Lex(); // Eat shift type token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004219
Jim Grosbachd3595712011-08-03 23:50:40 +00004220 // rrx stands alone.
4221 Amount = 0;
4222 if (St != ARM_AM::rrx) {
4223 Loc = Parser.getTok().getLoc();
4224 // A '#' and a shift amount.
4225 const AsmToken &HashTok = Parser.getTok();
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004226 if (HashTok.isNot(AsmToken::Hash) &&
4227 HashTok.isNot(AsmToken::Dollar))
Jim Grosbachd3595712011-08-03 23:50:40 +00004228 return Error(HashTok.getLoc(), "'#' expected");
4229 Parser.Lex(); // Eat hash token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004230
Jim Grosbachd3595712011-08-03 23:50:40 +00004231 const MCExpr *Expr;
4232 if (getParser().ParseExpression(Expr))
4233 return true;
4234 // Range check the immediate.
4235 // lsl, ror: 0 <= imm <= 31
4236 // lsr, asr: 0 <= imm <= 32
4237 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4238 if (!CE)
4239 return Error(Loc, "shift amount must be an immediate");
4240 int64_t Imm = CE->getValue();
4241 if (Imm < 0 ||
4242 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4243 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4244 return Error(Loc, "immediate shift value out of range");
4245 Amount = Imm;
4246 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004247
4248 return false;
4249}
4250
Jim Grosbache7fbce72011-10-03 23:38:36 +00004251/// parseFPImm - A floating point immediate expression operand.
4252ARMAsmParser::OperandMatchResultTy ARMAsmParser::
4253parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004254 // Anything that can accept a floating point constant as an operand
4255 // needs to go through here, as the regular ParseExpression is
4256 // integer only.
4257 //
4258 // This routine still creates a generic Immediate operand, containing
4259 // a bitcast of the 64-bit floating point value. The various operands
4260 // that accept floats can check whether the value is valid for them
4261 // via the standard is*() predicates.
4262
Jim Grosbache7fbce72011-10-03 23:38:36 +00004263 SMLoc S = Parser.getTok().getLoc();
4264
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004265 if (Parser.getTok().isNot(AsmToken::Hash) &&
4266 Parser.getTok().isNot(AsmToken::Dollar))
Jim Grosbache7fbce72011-10-03 23:38:36 +00004267 return MatchOperand_NoMatch;
Jim Grosbach741cd732011-10-17 22:26:03 +00004268
4269 // Disambiguate the VMOV forms that can accept an FP immediate.
4270 // vmov.f32 <sreg>, #imm
4271 // vmov.f64 <dreg>, #imm
4272 // vmov.f32 <dreg>, #imm @ vector f32x2
4273 // vmov.f32 <qreg>, #imm @ vector f32x4
4274 //
4275 // There are also the NEON VMOV instructions which expect an
4276 // integer constant. Make sure we don't try to parse an FPImm
4277 // for these:
4278 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4279 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4280 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4281 TyOp->getToken() != ".f64"))
4282 return MatchOperand_NoMatch;
4283
Jim Grosbache7fbce72011-10-03 23:38:36 +00004284 Parser.Lex(); // Eat the '#'.
4285
4286 // Handle negation, as that still comes through as a separate token.
4287 bool isNegative = false;
4288 if (Parser.getTok().is(AsmToken::Minus)) {
4289 isNegative = true;
4290 Parser.Lex();
4291 }
4292 const AsmToken &Tok = Parser.getTok();
Jim Grosbach235c8d22012-01-19 02:47:30 +00004293 SMLoc Loc = Tok.getLoc();
Jim Grosbache7fbce72011-10-03 23:38:36 +00004294 if (Tok.is(AsmToken::Real)) {
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004295 APFloat RealVal(APFloat::IEEEsingle, Tok.getString());
Jim Grosbache7fbce72011-10-03 23:38:36 +00004296 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4297 // If we had a '-' in front, toggle the sign bit.
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004298 IntVal ^= (uint64_t)isNegative << 31;
Jim Grosbache7fbce72011-10-03 23:38:36 +00004299 Parser.Lex(); // Eat the token.
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004300 Operands.push_back(ARMOperand::CreateImm(
4301 MCConstantExpr::Create(IntVal, getContext()),
4302 S, Parser.getTok().getLoc()));
Jim Grosbache7fbce72011-10-03 23:38:36 +00004303 return MatchOperand_Success;
4304 }
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004305 // Also handle plain integers. Instructions which allow floating point
4306 // immediates also allow a raw encoded 8-bit value.
Jim Grosbache7fbce72011-10-03 23:38:36 +00004307 if (Tok.is(AsmToken::Integer)) {
4308 int64_t Val = Tok.getIntVal();
4309 Parser.Lex(); // Eat the token.
4310 if (Val > 255 || Val < 0) {
Jim Grosbach235c8d22012-01-19 02:47:30 +00004311 Error(Loc, "encoded floating point value out of range");
Jim Grosbache7fbce72011-10-03 23:38:36 +00004312 return MatchOperand_ParseFail;
4313 }
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004314 double RealVal = ARM_AM::getFPImmFloat(Val);
4315 Val = APFloat(APFloat::IEEEdouble, RealVal).bitcastToAPInt().getZExtValue();
4316 Operands.push_back(ARMOperand::CreateImm(
4317 MCConstantExpr::Create(Val, getContext()), S,
4318 Parser.getTok().getLoc()));
Jim Grosbache7fbce72011-10-03 23:38:36 +00004319 return MatchOperand_Success;
4320 }
4321
Jim Grosbach235c8d22012-01-19 02:47:30 +00004322 Error(Loc, "invalid floating point immediate");
Jim Grosbache7fbce72011-10-03 23:38:36 +00004323 return MatchOperand_ParseFail;
4324}
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004325
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004326/// Parse a arm instruction operand. For now this parses the operand regardless
4327/// of the mnemonic.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004328bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004329 StringRef Mnemonic) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004330 SMLoc S, E;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004331
4332 // Check if the current operand has a custom associated parser, if so, try to
4333 // custom parse the operand, or fallback to the general approach.
Jim Grosbach861e49c2011-02-12 01:34:40 +00004334 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4335 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004336 return false;
Jim Grosbach861e49c2011-02-12 01:34:40 +00004337 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4338 // there was a match, but an error occurred, in which case, just return that
4339 // the operand parsing failed.
4340 if (ResTy == MatchOperand_ParseFail)
4341 return true;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004342
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004343 switch (getLexer().getKind()) {
Bill Wendlingee7f1f92010-11-06 21:42:12 +00004344 default:
4345 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling2063b842010-11-18 23:43:05 +00004346 return true;
Jim Grosbachbb24c592011-07-13 18:49:30 +00004347 case AsmToken::Identifier: {
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004348 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling2063b842010-11-18 23:43:05 +00004349 return false;
Jim Grosbach0d6022d2011-07-26 20:41:24 +00004350 int Res = tryParseShiftRegister(Operands);
Jim Grosbachbb24c592011-07-13 18:49:30 +00004351 if (Res == 0) // success
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004352 return false;
Jim Grosbachbb24c592011-07-13 18:49:30 +00004353 else if (Res == -1) // irrecoverable error
4354 return true;
Jim Grosbach4eda1452011-12-20 22:26:38 +00004355 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach4ab23b52011-10-03 21:12:43 +00004356 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
4357 S = Parser.getTok().getLoc();
4358 Parser.Lex();
4359 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
4360 return false;
4361 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00004362
4363 // Fall though for the Identifier case that is not a register or a
4364 // special name.
Jim Grosbachbb24c592011-07-13 18:49:30 +00004365 }
Jim Grosbach4e380352011-10-26 21:14:08 +00004366 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderbyb084be92011-01-13 20:32:36 +00004367 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach5c6b6342011-11-01 22:38:31 +00004368 case AsmToken::String: // quoted label names.
Kevin Enderbyb084be92011-01-13 20:32:36 +00004369 case AsmToken::Dot: { // . as a branch target
Kevin Enderby146dcf22009-10-15 20:48:48 +00004370 // This was not a register so parse other operands that start with an
4371 // identifier (like labels) as expressions and create them as immediates.
4372 const MCExpr *IdVal;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004373 S = Parser.getTok().getLoc();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004374 if (getParser().ParseExpression(IdVal))
Bill Wendling2063b842010-11-18 23:43:05 +00004375 return true;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004376 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling2063b842010-11-18 23:43:05 +00004377 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4378 return false;
4379 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004380 case AsmToken::LBrac:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004381 return parseMemory(Operands);
Kevin Enderbya2b99102009-10-09 21:12:28 +00004382 case AsmToken::LCurly:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004383 return parseRegisterList(Operands);
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004384 case AsmToken::Dollar:
Owen Andersonf02d98d2011-08-29 17:17:09 +00004385 case AsmToken::Hash: {
Kevin Enderby3a80dac2009-10-13 23:33:38 +00004386 // #42 -> immediate.
4387 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004388 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00004389 Parser.Lex();
Owen Andersonf02d98d2011-08-29 17:17:09 +00004390 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby146dcf22009-10-15 20:48:48 +00004391 const MCExpr *ImmVal;
4392 if (getParser().ParseExpression(ImmVal))
Bill Wendling2063b842010-11-18 23:43:05 +00004393 return true;
Owen Andersonf02d98d2011-08-29 17:17:09 +00004394 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbach7f1f3bd2011-11-01 22:37:37 +00004395 if (CE) {
4396 int32_t Val = CE->getValue();
4397 if (isNegative && Val == 0)
4398 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Andersonf02d98d2011-08-29 17:17:09 +00004399 }
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004400 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling2063b842010-11-18 23:43:05 +00004401 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4402 return false;
Owen Andersonf02d98d2011-08-29 17:17:09 +00004403 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00004404 case AsmToken::Colon: {
4405 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng965b3c72011-01-13 07:58:56 +00004406 // FIXME: Check it's an expression prefix,
4407 // e.g. (FOO - :lower16:BAR) isn't legal.
4408 ARMMCExpr::VariantKind RefKind;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004409 if (parsePrefix(RefKind))
Jason W Kim1f7bc072011-01-11 23:53:41 +00004410 return true;
4411
Evan Cheng965b3c72011-01-13 07:58:56 +00004412 const MCExpr *SubExprVal;
4413 if (getParser().ParseExpression(SubExprVal))
Jason W Kim1f7bc072011-01-11 23:53:41 +00004414 return true;
4415
Evan Cheng965b3c72011-01-13 07:58:56 +00004416 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4417 getContext());
Jason W Kim1f7bc072011-01-11 23:53:41 +00004418 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng965b3c72011-01-13 07:58:56 +00004419 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim1f7bc072011-01-11 23:53:41 +00004420 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004421 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00004422 }
4423}
4424
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004425// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng965b3c72011-01-13 07:58:56 +00004426// :lower16: and :upper16:.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004427bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng965b3c72011-01-13 07:58:56 +00004428 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim1f7bc072011-01-11 23:53:41 +00004429
4430 // :lower16: and :upper16: modifiers
Jason W Kim93229972011-01-13 00:27:00 +00004431 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim1f7bc072011-01-11 23:53:41 +00004432 Parser.Lex(); // Eat ':'
4433
4434 if (getLexer().isNot(AsmToken::Identifier)) {
4435 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4436 return true;
4437 }
4438
4439 StringRef IDVal = Parser.getTok().getIdentifier();
4440 if (IDVal == "lower16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00004441 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00004442 } else if (IDVal == "upper16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00004443 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00004444 } else {
4445 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4446 return true;
4447 }
4448 Parser.Lex();
4449
4450 if (getLexer().isNot(AsmToken::Colon)) {
4451 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4452 return true;
4453 }
4454 Parser.Lex(); // Eat the last ':'
4455 return false;
4456}
4457
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004458/// \brief Given a mnemonic, split out possible predication code and carry
4459/// setting letters to form a canonical mnemonic and flags.
4460//
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004461// FIXME: Would be nice to autogen this.
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004462// FIXME: This is a bit of a maze of special cases.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004463StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00004464 unsigned &PredicationCode,
4465 bool &CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004466 unsigned &ProcessorIMod,
4467 StringRef &ITMask) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004468 PredicationCode = ARMCC::AL;
4469 CarrySetting = false;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004470 ProcessorIMod = 0;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004471
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004472 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004473 //
4474 // FIXME: Would be nice to autogen this.
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00004475 if ((Mnemonic == "movs" && isThumb()) ||
4476 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4477 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4478 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4479 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4480 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4481 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
Jim Grosbache16acac2011-12-19 19:43:50 +00004482 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" ||
4483 Mnemonic == "fmuls")
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004484 return Mnemonic;
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004485
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00004486 // First, split out any predication code. Ignore mnemonics we know aren't
4487 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbach8d114902011-07-20 18:20:31 +00004488 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach0c398b92011-07-27 21:58:11 +00004489 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach3636be32011-08-22 23:55:58 +00004490 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbachf6d5d602011-09-01 18:22:13 +00004491 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00004492 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4493 .Case("eq", ARMCC::EQ)
4494 .Case("ne", ARMCC::NE)
4495 .Case("hs", ARMCC::HS)
4496 .Case("cs", ARMCC::HS)
4497 .Case("lo", ARMCC::LO)
4498 .Case("cc", ARMCC::LO)
4499 .Case("mi", ARMCC::MI)
4500 .Case("pl", ARMCC::PL)
4501 .Case("vs", ARMCC::VS)
4502 .Case("vc", ARMCC::VC)
4503 .Case("hi", ARMCC::HI)
4504 .Case("ls", ARMCC::LS)
4505 .Case("ge", ARMCC::GE)
4506 .Case("lt", ARMCC::LT)
4507 .Case("gt", ARMCC::GT)
4508 .Case("le", ARMCC::LE)
4509 .Case("al", ARMCC::AL)
4510 .Default(~0U);
4511 if (CC != ~0U) {
4512 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4513 PredicationCode = CC;
4514 }
Bill Wendling193961b2010-10-29 23:50:21 +00004515 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004516
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004517 // Next, determine if we have a carry setting bit. We explicitly ignore all
4518 // the instructions we know end in 's'.
4519 if (Mnemonic.endswith("s") &&
Jim Grosbachd3e8e292011-08-17 22:49:09 +00004520 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00004521 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4522 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4523 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach086d0132011-12-08 00:49:29 +00004524 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach54337b82011-12-10 00:01:02 +00004525 Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
Jim Grosbach92a939a2011-12-19 19:02:41 +00004526 Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" ||
Jim Grosbach489ed592011-12-22 19:20:45 +00004527 Mnemonic == "fmuls" || Mnemonic == "fcmps" ||
Jim Grosbach51726e22011-07-29 20:26:09 +00004528 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004529 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4530 CarrySetting = true;
4531 }
4532
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004533 // The "cps" instruction can have a interrupt mode operand which is glued into
4534 // the mnemonic. Check if this is the case, split it and parse the imod op
4535 if (Mnemonic.startswith("cps")) {
4536 // Split out any imod code.
4537 unsigned IMod =
4538 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4539 .Case("ie", ARM_PROC::IE)
4540 .Case("id", ARM_PROC::ID)
4541 .Default(~0U);
4542 if (IMod != ~0U) {
4543 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4544 ProcessorIMod = IMod;
4545 }
4546 }
4547
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004548 // The "it" instruction has the condition mask on the end of the mnemonic.
4549 if (Mnemonic.startswith("it")) {
4550 ITMask = Mnemonic.slice(2, Mnemonic.size());
4551 Mnemonic = Mnemonic.slice(0, 2);
4552 }
4553
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004554 return Mnemonic;
4555}
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004556
4557/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4558/// inclusion of carry set or predication code operands.
4559//
4560// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00004561void ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004562getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00004563 bool &CanAcceptPredicationCode) {
Daniel Dunbar09264122011-01-11 19:06:29 +00004564 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4565 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00004566 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00004567 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004568 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00004569 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004570 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00004571 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004572 Mnemonic == "mla" || Mnemonic == "smlal" ||
4573 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbar09264122011-01-11 19:06:29 +00004574 CanAcceptCarrySet = true;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004575 } else
Daniel Dunbar09264122011-01-11 19:06:29 +00004576 CanAcceptCarrySet = false;
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004577
Daniel Dunbar09264122011-01-11 19:06:29 +00004578 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4579 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4580 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4581 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbach803898f2011-09-06 20:27:04 +00004582 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4583 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach25977222011-08-19 23:24:36 +00004584 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach93981412011-10-11 21:55:36 +00004585 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4586 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4587 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbachb9d4e372011-08-26 22:21:51 +00004588 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4589 !isThumb()) ||
Jim Grosbachb908b7a2011-09-10 00:15:36 +00004590 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004591 CanAcceptPredicationCode = false;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004592 } else
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004593 CanAcceptPredicationCode = true;
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004594
Jim Grosbach6c45b752011-09-16 16:39:25 +00004595 if (isThumb()) {
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004596 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbachb98ab912011-06-30 22:10:46 +00004597 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004598 CanAcceptPredicationCode = false;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004599 }
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004600}
4601
Jim Grosbach7283da92011-08-16 21:12:37 +00004602bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4603 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004604 // FIXME: This is all horribly hacky. We really need a better way to deal
4605 // with optional operands like this in the matcher table.
Jim Grosbach7283da92011-08-16 21:12:37 +00004606
4607 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4608 // another does not. Specifically, the MOVW instruction does not. So we
4609 // special case it here and remove the defaulted (non-setting) cc_out
4610 // operand if that's the instruction we're trying to match.
4611 //
4612 // We do this as post-processing of the explicit operands rather than just
4613 // conditionally adding the cc_out in the first place because we need
4614 // to check the type of the parsed immediate operand.
Owen Andersond7791b92011-09-14 22:46:14 +00004615 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbach7283da92011-08-16 21:12:37 +00004616 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4617 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4618 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4619 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00004620
4621 // Register-register 'add' for thumb does not have a cc_out operand
4622 // when there are only two register operands.
4623 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4624 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4625 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4626 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4627 return true;
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004628 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004629 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4630 // have to check the immediate range here since Thumb2 has a variant
4631 // that can handle a different range and has a cc_out operand.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004632 if (((isThumb() && Mnemonic == "add") ||
4633 (isThumbTwo() && Mnemonic == "sub")) &&
4634 Operands.size() == 6 &&
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004635 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4636 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4637 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004638 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4639 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4640 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004641 return true;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004642 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4643 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004644 // selecting via the generic "add" mnemonic, so to know that we
4645 // should remove the cc_out operand, we have to explicitly check that
4646 // it's not one of the other variants. Ugh.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004647 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4648 Operands.size() == 6 &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004649 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4650 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4651 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4652 // Nest conditions rather than one big 'if' statement for readability.
4653 //
4654 // If either register is a high reg, it's either one of the SP
4655 // variants (handled above) or a 32-bit encoding, so we just
Jim Grosbach78dcaed2012-01-21 00:07:56 +00004656 // check against T3. If the second register is the PC, this is an
4657 // alternate form of ADR, which uses encoding T4, so check for that too.
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004658 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4659 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
Jim Grosbach78dcaed2012-01-21 00:07:56 +00004660 static_cast<ARMOperand*>(Operands[4])->getReg() != ARM::PC &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004661 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4662 return false;
4663 // If both registers are low, we're in an IT block, and the immediate is
4664 // in range, we should use encoding T1 instead, which has a cc_out.
4665 if (inITBlock() &&
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004666 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004667 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4668 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4669 return false;
4670
4671 // Otherwise, we use encoding T4, which does not have a cc_out
4672 // operand.
4673 return true;
4674 }
4675
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004676 // The thumb2 multiply instruction doesn't have a CCOut register, so
4677 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4678 // use the 16-bit encoding or not.
4679 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4680 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4681 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4682 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4683 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4684 // If the registers aren't low regs, the destination reg isn't the
4685 // same as one of the source regs, or the cc_out operand is zero
4686 // outside of an IT block, we have to use the 32-bit encoding, so
4687 // remove the cc_out operand.
4688 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4689 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach6efa7b92011-11-15 19:29:45 +00004690 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004691 !inITBlock() ||
4692 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4693 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4694 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4695 static_cast<ARMOperand*>(Operands[4])->getReg())))
4696 return true;
4697
Jim Grosbachefa7e952011-11-15 19:55:16 +00004698 // Also check the 'mul' syntax variant that doesn't specify an explicit
4699 // destination register.
4700 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4701 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4702 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4703 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4704 // If the registers aren't low regs or the cc_out operand is zero
4705 // outside of an IT block, we have to use the 32-bit encoding, so
4706 // remove the cc_out operand.
4707 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4708 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4709 !inITBlock()))
4710 return true;
4711
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004712
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004713
Jim Grosbach4b701af2011-08-24 21:42:27 +00004714 // Register-register 'add/sub' for thumb does not have a cc_out operand
4715 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4716 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4717 // right, this will result in better diagnostics (which operand is off)
4718 // anyway.
4719 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4720 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004721 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4722 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4723 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4724 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00004725
Jim Grosbach7283da92011-08-16 21:12:37 +00004726 return false;
4727}
4728
Jim Grosbach12952fe2011-11-11 23:08:10 +00004729static bool isDataTypeToken(StringRef Tok) {
4730 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4731 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4732 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4733 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4734 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4735 Tok == ".f" || Tok == ".d";
4736}
4737
4738// FIXME: This bit should probably be handled via an explicit match class
4739// in the .td files that matches the suffix instead of having it be
4740// a literal string token the way it is now.
4741static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4742 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4743}
4744
Jim Grosbach8be2f652011-12-09 23:34:09 +00004745static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004746/// Parse an arm instruction mnemonic followed by its operands.
4747bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4748 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach8be2f652011-12-09 23:34:09 +00004749 // Apply mnemonic aliases before doing anything else, as the destination
4750 // mnemnonic may include suffices and we want to handle them normally.
4751 // The generic tblgen'erated code does this later, at the start of
4752 // MatchInstructionImpl(), but that's too late for aliases that include
4753 // any sort of suffix.
4754 unsigned AvailableFeatures = getAvailableFeatures();
4755 applyMnemonicAliases(Name, AvailableFeatures);
4756
Jim Grosbachab5830e2011-12-14 02:16:11 +00004757 // First check for the ARM-specific .req directive.
4758 if (Parser.getTok().is(AsmToken::Identifier) &&
4759 Parser.getTok().getIdentifier() == ".req") {
4760 parseDirectiveReq(Name, NameLoc);
4761 // We always return 'error' for this, as we're done with this
4762 // statement and don't need to match the 'instruction."
4763 return true;
4764 }
4765
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004766 // Create the leading tokens for the mnemonic, split by '.' characters.
4767 size_t Start = 0, Next = Name.find('.');
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004768 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004769
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004770 // Split out the predication code and carry setting flag from the mnemonic.
4771 unsigned PredicationCode;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004772 unsigned ProcessorIMod;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004773 bool CarrySetting;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004774 StringRef ITMask;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004775 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004776 ProcessorIMod, ITMask);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004777
Jim Grosbach1c171b12011-08-25 17:23:55 +00004778 // In Thumb1, only the branch (B) instruction can be predicated.
4779 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4780 Parser.EatToEndOfStatement();
4781 return Error(NameLoc, "conditional execution not supported in Thumb1");
4782 }
4783
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004784 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4785
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004786 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4787 // is the mask as it will be for the IT encoding if the conditional
4788 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4789 // where the conditional bit0 is zero, the instruction post-processing
4790 // will adjust the mask accordingly.
4791 if (Mnemonic == "it") {
Jim Grosbached16ec42011-08-29 22:24:09 +00004792 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4793 if (ITMask.size() > 3) {
4794 Parser.EatToEndOfStatement();
4795 return Error(Loc, "too many conditions on IT instruction");
4796 }
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004797 unsigned Mask = 8;
4798 for (unsigned i = ITMask.size(); i != 0; --i) {
4799 char pos = ITMask[i - 1];
4800 if (pos != 't' && pos != 'e') {
4801 Parser.EatToEndOfStatement();
Jim Grosbached16ec42011-08-29 22:24:09 +00004802 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004803 }
4804 Mask >>= 1;
4805 if (ITMask[i - 1] == 't')
4806 Mask |= 8;
4807 }
Jim Grosbached16ec42011-08-29 22:24:09 +00004808 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004809 }
4810
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004811 // FIXME: This is all a pretty gross hack. We should automatically handle
4812 // optional operands like this via tblgen.
Bill Wendling219dabd2010-11-21 10:56:05 +00004813
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004814 // Next, add the CCOut and ConditionCode operands, if needed.
4815 //
4816 // For mnemonics which can ever incorporate a carry setting bit or predication
4817 // code, our matching model involves us always generating CCOut and
4818 // ConditionCode operands to match the mnemonic "as written" and then we let
4819 // the matcher deal with finding the right instruction or generating an
4820 // appropriate error.
4821 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004822 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004823
Jim Grosbach03a8a162011-07-14 22:04:21 +00004824 // If we had a carry-set on an instruction that can't do that, issue an
4825 // error.
4826 if (!CanAcceptCarrySet && CarrySetting) {
4827 Parser.EatToEndOfStatement();
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004828 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach03a8a162011-07-14 22:04:21 +00004829 "' can not set flags, but 's' suffix specified");
4830 }
Jim Grosbach0a547702011-07-22 17:44:50 +00004831 // If we had a predication code on an instruction that can't do that, issue an
4832 // error.
4833 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4834 Parser.EatToEndOfStatement();
4835 return Error(NameLoc, "instruction '" + Mnemonic +
4836 "' is not predicable, but condition code specified");
4837 }
Jim Grosbach03a8a162011-07-14 22:04:21 +00004838
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004839 // Add the carry setting operand, if necessary.
Jim Grosbached16ec42011-08-29 22:24:09 +00004840 if (CanAcceptCarrySet) {
4841 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004842 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbached16ec42011-08-29 22:24:09 +00004843 Loc));
4844 }
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004845
4846 // Add the predication code operand, if necessary.
4847 if (CanAcceptPredicationCode) {
Jim Grosbached16ec42011-08-29 22:24:09 +00004848 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4849 CarrySetting);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004850 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbached16ec42011-08-29 22:24:09 +00004851 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004852 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004853
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004854 // Add the processor imod operand, if necessary.
4855 if (ProcessorIMod) {
4856 Operands.push_back(ARMOperand::CreateImm(
4857 MCConstantExpr::Create(ProcessorIMod, getContext()),
4858 NameLoc, NameLoc));
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004859 }
4860
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004861 // Add the remaining tokens in the mnemonic.
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004862 while (Next != StringRef::npos) {
4863 Start = Next;
4864 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004865 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004866
Jim Grosbach12952fe2011-11-11 23:08:10 +00004867 // Some NEON instructions have an optional datatype suffix that is
4868 // completely ignored. Check for that.
4869 if (isDataTypeToken(ExtraToken) &&
4870 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4871 continue;
4872
Jim Grosbach39c6e1d2011-09-07 16:06:04 +00004873 if (ExtraToken != ".n") {
4874 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4875 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4876 }
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004877 }
4878
4879 // Read the remaining operands.
4880 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004881 // Read the first operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004882 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnera2a9d162010-09-11 16:18:25 +00004883 Parser.EatToEndOfStatement();
4884 return true;
4885 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004886
4887 while (getLexer().is(AsmToken::Comma)) {
Sean Callanana83fd7d2010-01-19 20:27:46 +00004888 Parser.Lex(); // Eat the comma.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004889
4890 // Parse and remember the operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004891 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnera2a9d162010-09-11 16:18:25 +00004892 Parser.EatToEndOfStatement();
4893 return true;
4894 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004895 }
4896 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00004897
Chris Lattnera2a9d162010-09-11 16:18:25 +00004898 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbachb8d9f512011-10-07 18:27:04 +00004899 SMLoc Loc = getLexer().getLoc();
Chris Lattnera2a9d162010-09-11 16:18:25 +00004900 Parser.EatToEndOfStatement();
Jim Grosbachb8d9f512011-10-07 18:27:04 +00004901 return Error(Loc, "unexpected token in argument list");
Chris Lattnera2a9d162010-09-11 16:18:25 +00004902 }
Bill Wendlingee7f1f92010-11-06 21:42:12 +00004903
Chris Lattner91689c12010-09-08 05:10:46 +00004904 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004905
Jim Grosbach7283da92011-08-16 21:12:37 +00004906 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4907 // do and don't have a cc_out optional-def operand. With some spot-checks
4908 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004909 // parse and adjust accordingly before actually matching. We shouldn't ever
4910 // try to remove a cc_out operand that was explicitly set on the the
4911 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4912 // table driven matcher doesn't fit well with the ARM instruction set.
4913 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004914 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4915 Operands.erase(Operands.begin() + 1);
4916 delete Op;
4917 }
4918
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00004919 // ARM mode 'blx' need special handling, as the register operand version
4920 // is predicable, but the label operand version is not. So, we can't rely
4921 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach6e5778f2011-10-07 23:24:09 +00004922 // a k_CondCode operand in the list. If we're trying to match the label
4923 // version, remove the k_CondCode operand here.
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00004924 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4925 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4926 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4927 Operands.erase(Operands.begin() + 1);
4928 delete Op;
4929 }
Jim Grosbach8cffa282011-08-11 23:51:13 +00004930
4931 // The vector-compare-to-zero instructions have a literal token "#0" at
4932 // the end that comes to here as an immediate operand. Convert it to a
4933 // token to play nicely with the matcher.
4934 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4935 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4936 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4937 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4938 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4939 if (CE && CE->getValue() == 0) {
4940 Operands.erase(Operands.begin() + 5);
4941 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4942 delete Op;
4943 }
4944 }
Jim Grosbach46b66462011-10-03 22:30:24 +00004945 // VCMP{E} does the same thing, but with a different operand count.
4946 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4947 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4948 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4949 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4950 if (CE && CE->getValue() == 0) {
4951 Operands.erase(Operands.begin() + 4);
4952 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4953 delete Op;
4954 }
4955 }
Jim Grosbachc3c32d92011-08-22 23:47:13 +00004956 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
Jim Grosbach1f1a3592011-12-13 20:50:38 +00004957 // end. Convert it to a token here. Take care not to convert those
4958 // that should hit the Thumb2 encoding.
Jim Grosbachc3c32d92011-08-22 23:47:13 +00004959 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
Jim Grosbach1f1a3592011-12-13 20:50:38 +00004960 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4961 static_cast<ARMOperand*>(Operands[4])->isReg() &&
Jim Grosbachc3c32d92011-08-22 23:47:13 +00004962 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4963 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4964 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
Jim Grosbach1f1a3592011-12-13 20:50:38 +00004965 if (CE && CE->getValue() == 0 &&
4966 (isThumbOne() ||
Jim Grosbach5ac89672011-12-13 21:06:41 +00004967 // The cc_out operand matches the IT block.
4968 ((inITBlock() != CarrySetting) &&
4969 // Neither register operand is a high register.
Jim Grosbach1f1a3592011-12-13 20:50:38 +00004970 (isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach5ac89672011-12-13 21:06:41 +00004971 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()))))){
Jim Grosbachc3c32d92011-08-22 23:47:13 +00004972 Operands.erase(Operands.begin() + 5);
4973 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4974 delete Op;
4975 }
4976 }
4977
Chris Lattnerf29c0b62010-01-14 22:21:20 +00004978 return false;
Kevin Enderbyccab3172009-09-15 00:27:25 +00004979}
4980
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004981// Validate context-sensitive operand constraints.
Jim Grosbach169b2be2011-08-23 18:13:04 +00004982
4983// return 'true' if register list contains non-low GPR registers,
4984// 'false' otherwise. If Reg is in the register list or is HiReg, set
4985// 'containsReg' to true.
4986static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4987 unsigned HiReg, bool &containsReg) {
4988 containsReg = false;
4989 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4990 unsigned OpReg = Inst.getOperand(i).getReg();
4991 if (OpReg == Reg)
4992 containsReg = true;
4993 // Anything other than a low register isn't legal here.
4994 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4995 return true;
4996 }
4997 return false;
4998}
4999
Jim Grosbacha31f2232011-09-07 18:05:34 +00005000// Check if the specified regisgter is in the register list of the inst,
5001// starting at the indicated operand number.
5002static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
5003 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5004 unsigned OpReg = Inst.getOperand(i).getReg();
5005 if (OpReg == Reg)
5006 return true;
5007 }
5008 return false;
5009}
5010
Jim Grosbached16ec42011-08-29 22:24:09 +00005011// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
5012// the ARMInsts array) instead. Getting that here requires awkward
5013// API changes, though. Better way?
5014namespace llvm {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00005015extern const MCInstrDesc ARMInsts[];
Jim Grosbached16ec42011-08-29 22:24:09 +00005016}
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00005017static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbached16ec42011-08-29 22:24:09 +00005018 return ARMInsts[Opcode];
5019}
5020
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005021// FIXME: We would really like to be able to tablegen'erate this.
5022bool ARMAsmParser::
5023validateInstruction(MCInst &Inst,
5024 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00005025 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbached16ec42011-08-29 22:24:09 +00005026 SMLoc Loc = Operands[0]->getStartLoc();
5027 // Check the IT block state first.
Owen Anderson44ae2da2011-09-13 17:59:19 +00005028 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
5029 // being allowed in IT blocks, but not being predicable. It just always
5030 // executes.
5031 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbached16ec42011-08-29 22:24:09 +00005032 unsigned bit = 1;
5033 if (ITState.FirstCond)
5034 ITState.FirstCond = false;
5035 else
Jim Grosbacha0d34d32011-09-02 23:22:08 +00005036 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbached16ec42011-08-29 22:24:09 +00005037 // The instruction must be predicable.
5038 if (!MCID.isPredicable())
5039 return Error(Loc, "instructions in IT block must be predicable");
5040 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
5041 unsigned ITCond = bit ? ITState.Cond :
5042 ARMCC::getOppositeCondition(ITState.Cond);
5043 if (Cond != ITCond) {
5044 // Find the condition code Operand to get its SMLoc information.
5045 SMLoc CondLoc;
5046 for (unsigned i = 1; i < Operands.size(); ++i)
5047 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
5048 CondLoc = Operands[i]->getStartLoc();
5049 return Error(CondLoc, "incorrect condition in IT block; got '" +
5050 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
5051 "', but expected '" +
5052 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
5053 }
Jim Grosbachc61fc8f2011-08-31 18:29:05 +00005054 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00005055 } else if (isThumbTwo() && MCID.isPredicable() &&
5056 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson29cfe6c2011-09-09 21:48:23 +00005057 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
5058 Inst.getOpcode() != ARM::t2B)
Jim Grosbached16ec42011-08-29 22:24:09 +00005059 return Error(Loc, "predicated instructions must be in IT block");
5060
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005061 switch (Inst.getOpcode()) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00005062 case ARM::LDRD:
5063 case ARM::LDRD_PRE:
5064 case ARM::LDRD_POST:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005065 case ARM::LDREXD: {
5066 // Rt2 must be Rt + 1.
5067 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5068 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5069 if (Rt2 != Rt + 1)
5070 return Error(Operands[3]->getStartLoc(),
5071 "destination operands must be sequential");
5072 return false;
5073 }
Jim Grosbacheb09f492011-08-11 20:28:23 +00005074 case ARM::STRD: {
5075 // Rt2 must be Rt + 1.
5076 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5077 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5078 if (Rt2 != Rt + 1)
5079 return Error(Operands[3]->getStartLoc(),
5080 "source operands must be sequential");
5081 return false;
5082 }
Jim Grosbachf7164b22011-08-10 20:49:18 +00005083 case ARM::STRD_PRE:
5084 case ARM::STRD_POST:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005085 case ARM::STREXD: {
5086 // Rt2 must be Rt + 1.
5087 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5088 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
5089 if (Rt2 != Rt + 1)
Jim Grosbacheb09f492011-08-11 20:28:23 +00005090 return Error(Operands[3]->getStartLoc(),
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005091 "source operands must be sequential");
5092 return false;
5093 }
Jim Grosbach03f56d92011-07-27 21:09:25 +00005094 case ARM::SBFX:
5095 case ARM::UBFX: {
5096 // width must be in range [1, 32-lsb]
5097 unsigned lsb = Inst.getOperand(2).getImm();
5098 unsigned widthm1 = Inst.getOperand(3).getImm();
5099 if (widthm1 >= 32 - lsb)
5100 return Error(Operands[5]->getStartLoc(),
5101 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach64610e52011-08-16 21:42:31 +00005102 return false;
Jim Grosbach03f56d92011-07-27 21:09:25 +00005103 }
Jim Grosbach90103cc2011-08-18 21:50:53 +00005104 case ARM::tLDMIA: {
Jim Grosbacha31f2232011-09-07 18:05:34 +00005105 // If we're parsing Thumb2, the .w variant is available and handles
5106 // most cases that are normally illegal for a Thumb1 LDM
5107 // instruction. We'll make the transformation in processInstruction()
5108 // if necessary.
5109 //
Jim Grosbach90103cc2011-08-18 21:50:53 +00005110 // Thumb LDM instructions are writeback iff the base register is not
5111 // in the register list.
5112 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach139acd22011-08-22 23:01:07 +00005113 bool hasWritebackToken =
5114 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5115 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbach169b2be2011-08-23 18:13:04 +00005116 bool listContainsBase;
Jim Grosbacha31f2232011-09-07 18:05:34 +00005117 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00005118 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
5119 "registers must be in range r0-r7");
Jim Grosbach90103cc2011-08-18 21:50:53 +00005120 // If we should have writeback, then there should be a '!' token.
Jim Grosbacha31f2232011-09-07 18:05:34 +00005121 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach90103cc2011-08-18 21:50:53 +00005122 return Error(Operands[2]->getStartLoc(),
5123 "writeback operator '!' expected");
Jim Grosbacha31f2232011-09-07 18:05:34 +00005124 // If we should not have writeback, there must not be a '!'. This is
5125 // true even for the 32-bit wide encodings.
Jim Grosbach169b2be2011-08-23 18:13:04 +00005126 if (listContainsBase && hasWritebackToken)
Jim Grosbach139acd22011-08-22 23:01:07 +00005127 return Error(Operands[3]->getStartLoc(),
5128 "writeback operator '!' not allowed when base register "
5129 "in register list");
Jim Grosbach90103cc2011-08-18 21:50:53 +00005130
5131 break;
5132 }
Jim Grosbacha31f2232011-09-07 18:05:34 +00005133 case ARM::t2LDMIA_UPD: {
5134 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
5135 return Error(Operands[4]->getStartLoc(),
5136 "writeback operator '!' not allowed when base register "
5137 "in register list");
5138 break;
5139 }
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005140 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
5141 // so only issue a diagnostic for thumb1. The instructions will be
5142 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach38c59fc2011-08-22 23:17:34 +00005143 case ARM::tPOP: {
Jim Grosbach169b2be2011-08-23 18:13:04 +00005144 bool listContainsBase;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005145 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
5146 !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00005147 return Error(Operands[2]->getStartLoc(),
5148 "registers must be in range r0-r7 or pc");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00005149 break;
5150 }
5151 case ARM::tPUSH: {
Jim Grosbach169b2be2011-08-23 18:13:04 +00005152 bool listContainsBase;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005153 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
5154 !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00005155 return Error(Operands[2]->getStartLoc(),
5156 "registers must be in range r0-r7 or lr");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00005157 break;
5158 }
Jim Grosbachd80d1692011-08-23 18:15:37 +00005159 case ARM::tSTMIA_UPD: {
5160 bool listContainsBase;
Jim Grosbach099c9762011-09-16 20:50:13 +00005161 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachd80d1692011-08-23 18:15:37 +00005162 return Error(Operands[4]->getStartLoc(),
5163 "registers must be in range r0-r7");
5164 break;
5165 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005166 }
5167
5168 return false;
5169}
5170
Jim Grosbach2c590522011-12-20 20:46:29 +00005171static unsigned getRealVSTLNOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbacheb538222011-12-02 22:34:51 +00005172 switch(Opc) {
5173 default: assert(0 && "unexpected opcode!");
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005174 // VST1LN
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005175 case ARM::VST1LNdWB_fixed_Asm_8:
Jim Grosbach2c590522011-12-20 20:46:29 +00005176 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005177 return ARM::VST1LNd8_UPD;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005178 case ARM::VST1LNdWB_fixed_Asm_16:
Jim Grosbach2c590522011-12-20 20:46:29 +00005179 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005180 return ARM::VST1LNd16_UPD;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005181 case ARM::VST1LNdWB_fixed_Asm_32:
Jim Grosbach2c590522011-12-20 20:46:29 +00005182 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005183 return ARM::VST1LNd32_UPD;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005184 case ARM::VST1LNdWB_register_Asm_8:
Jim Grosbach2c590522011-12-20 20:46:29 +00005185 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005186 return ARM::VST1LNd8_UPD;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005187 case ARM::VST1LNdWB_register_Asm_16:
Jim Grosbach2c590522011-12-20 20:46:29 +00005188 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005189 return ARM::VST1LNd16_UPD;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005190 case ARM::VST1LNdWB_register_Asm_32:
Jim Grosbach2c590522011-12-20 20:46:29 +00005191 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005192 return ARM::VST1LNd32_UPD;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005193 case ARM::VST1LNdAsm_8:
Jim Grosbach2c590522011-12-20 20:46:29 +00005194 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005195 return ARM::VST1LNd8;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005196 case ARM::VST1LNdAsm_16:
Jim Grosbach2c590522011-12-20 20:46:29 +00005197 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005198 return ARM::VST1LNd16;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005199 case ARM::VST1LNdAsm_32:
Jim Grosbach2c590522011-12-20 20:46:29 +00005200 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005201 return ARM::VST1LNd32;
5202
5203 // VST2LN
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005204 case ARM::VST2LNdWB_fixed_Asm_8:
Jim Grosbach2c590522011-12-20 20:46:29 +00005205 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005206 return ARM::VST2LNd8_UPD;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005207 case ARM::VST2LNdWB_fixed_Asm_16:
Jim Grosbach2c590522011-12-20 20:46:29 +00005208 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005209 return ARM::VST2LNd16_UPD;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005210 case ARM::VST2LNdWB_fixed_Asm_32:
Jim Grosbach2c590522011-12-20 20:46:29 +00005211 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005212 return ARM::VST2LNd32_UPD;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005213 case ARM::VST2LNqWB_fixed_Asm_16:
Jim Grosbach2c590522011-12-20 20:46:29 +00005214 Spacing = 2;
5215 return ARM::VST2LNq16_UPD;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005216 case ARM::VST2LNqWB_fixed_Asm_32:
Jim Grosbach2c590522011-12-20 20:46:29 +00005217 Spacing = 2;
5218 return ARM::VST2LNq32_UPD;
5219
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005220 case ARM::VST2LNdWB_register_Asm_8:
Jim Grosbach2c590522011-12-20 20:46:29 +00005221 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005222 return ARM::VST2LNd8_UPD;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005223 case ARM::VST2LNdWB_register_Asm_16:
Jim Grosbach2c590522011-12-20 20:46:29 +00005224 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005225 return ARM::VST2LNd16_UPD;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005226 case ARM::VST2LNdWB_register_Asm_32:
Jim Grosbach2c590522011-12-20 20:46:29 +00005227 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005228 return ARM::VST2LNd32_UPD;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005229 case ARM::VST2LNqWB_register_Asm_16:
Jim Grosbach2c590522011-12-20 20:46:29 +00005230 Spacing = 2;
5231 return ARM::VST2LNq16_UPD;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005232 case ARM::VST2LNqWB_register_Asm_32:
Jim Grosbach2c590522011-12-20 20:46:29 +00005233 Spacing = 2;
5234 return ARM::VST2LNq32_UPD;
5235
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005236 case ARM::VST2LNdAsm_8:
Jim Grosbach2c590522011-12-20 20:46:29 +00005237 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005238 return ARM::VST2LNd8;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005239 case ARM::VST2LNdAsm_16:
Jim Grosbach2c590522011-12-20 20:46:29 +00005240 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005241 return ARM::VST2LNd16;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005242 case ARM::VST2LNdAsm_32:
Jim Grosbach2c590522011-12-20 20:46:29 +00005243 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005244 return ARM::VST2LNd32;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005245 case ARM::VST2LNqAsm_16:
Jim Grosbach2c590522011-12-20 20:46:29 +00005246 Spacing = 2;
5247 return ARM::VST2LNq16;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005248 case ARM::VST2LNqAsm_32:
Jim Grosbach2c590522011-12-20 20:46:29 +00005249 Spacing = 2;
5250 return ARM::VST2LNq32;
Jim Grosbacheb538222011-12-02 22:34:51 +00005251 }
5252}
5253
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005254static unsigned getRealVLDLNOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach04945c42011-12-02 00:35:16 +00005255 switch(Opc) {
5256 default: assert(0 && "unexpected opcode!");
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005257 // VLD1LN
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005258 case ARM::VLD1LNdWB_fixed_Asm_8:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005259 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005260 return ARM::VLD1LNd8_UPD;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005261 case ARM::VLD1LNdWB_fixed_Asm_16:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005262 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005263 return ARM::VLD1LNd16_UPD;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005264 case ARM::VLD1LNdWB_fixed_Asm_32:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005265 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005266 return ARM::VLD1LNd32_UPD;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005267 case ARM::VLD1LNdWB_register_Asm_8:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005268 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005269 return ARM::VLD1LNd8_UPD;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005270 case ARM::VLD1LNdWB_register_Asm_16:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005271 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005272 return ARM::VLD1LNd16_UPD;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005273 case ARM::VLD1LNdWB_register_Asm_32:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005274 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005275 return ARM::VLD1LNd32_UPD;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005276 case ARM::VLD1LNdAsm_8:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005277 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005278 return ARM::VLD1LNd8;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005279 case ARM::VLD1LNdAsm_16:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005280 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005281 return ARM::VLD1LNd16;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005282 case ARM::VLD1LNdAsm_32:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005283 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005284 return ARM::VLD1LNd32;
5285
5286 // VLD2LN
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005287 case ARM::VLD2LNdWB_fixed_Asm_8:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005288 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005289 return ARM::VLD2LNd8_UPD;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005290 case ARM::VLD2LNdWB_fixed_Asm_16:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005291 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005292 return ARM::VLD2LNd16_UPD;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005293 case ARM::VLD2LNdWB_fixed_Asm_32:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005294 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005295 return ARM::VLD2LNd32_UPD;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005296 case ARM::VLD2LNqWB_fixed_Asm_16:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005297 Spacing = 1;
5298 return ARM::VLD2LNq16_UPD;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005299 case ARM::VLD2LNqWB_fixed_Asm_32:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005300 Spacing = 2;
5301 return ARM::VLD2LNq32_UPD;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005302 case ARM::VLD2LNdWB_register_Asm_8:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005303 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005304 return ARM::VLD2LNd8_UPD;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005305 case ARM::VLD2LNdWB_register_Asm_16:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005306 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005307 return ARM::VLD2LNd16_UPD;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005308 case ARM::VLD2LNdWB_register_Asm_32:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005309 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005310 return ARM::VLD2LNd32_UPD;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005311 case ARM::VLD2LNqWB_register_Asm_16:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005312 Spacing = 2;
5313 return ARM::VLD2LNq16_UPD;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005314 case ARM::VLD2LNqWB_register_Asm_32:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005315 Spacing = 2;
5316 return ARM::VLD2LNq32_UPD;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005317 case ARM::VLD2LNdAsm_8:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005318 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005319 return ARM::VLD2LNd8;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005320 case ARM::VLD2LNdAsm_16:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005321 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005322 return ARM::VLD2LNd16;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005323 case ARM::VLD2LNdAsm_32:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005324 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005325 return ARM::VLD2LNd32;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005326 case ARM::VLD2LNqAsm_16:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005327 Spacing = 2;
5328 return ARM::VLD2LNq16;
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005329 case ARM::VLD2LNqAsm_32:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005330 Spacing = 2;
5331 return ARM::VLD2LNq32;
Jim Grosbacha8b444b2012-01-23 21:53:26 +00005332
5333 // VLD3LN
5334 case ARM::VLD3LNdWB_fixed_Asm_8:
5335 Spacing = 1;
5336 return ARM::VLD3LNd8_UPD;
5337 case ARM::VLD3LNdWB_fixed_Asm_16:
5338 Spacing = 1;
5339 return ARM::VLD3LNd16_UPD;
5340 case ARM::VLD3LNdWB_fixed_Asm_32:
5341 Spacing = 1;
5342 return ARM::VLD3LNd32_UPD;
5343 case ARM::VLD3LNqWB_fixed_Asm_16:
5344 Spacing = 1;
5345 return ARM::VLD3LNq16_UPD;
5346 case ARM::VLD3LNqWB_fixed_Asm_32:
5347 Spacing = 2;
5348 return ARM::VLD3LNq32_UPD;
5349 case ARM::VLD3LNdWB_register_Asm_8:
5350 Spacing = 1;
5351 return ARM::VLD3LNd8_UPD;
5352 case ARM::VLD3LNdWB_register_Asm_16:
5353 Spacing = 1;
5354 return ARM::VLD3LNd16_UPD;
5355 case ARM::VLD3LNdWB_register_Asm_32:
5356 Spacing = 1;
5357 return ARM::VLD3LNd32_UPD;
5358 case ARM::VLD3LNqWB_register_Asm_16:
5359 Spacing = 2;
5360 return ARM::VLD3LNq16_UPD;
5361 case ARM::VLD3LNqWB_register_Asm_32:
5362 Spacing = 2;
5363 return ARM::VLD3LNq32_UPD;
5364 case ARM::VLD3LNdAsm_8:
5365 Spacing = 1;
5366 return ARM::VLD3LNd8;
5367 case ARM::VLD3LNdAsm_16:
5368 Spacing = 1;
5369 return ARM::VLD3LNd16;
5370 case ARM::VLD3LNdAsm_32:
5371 Spacing = 1;
5372 return ARM::VLD3LNd32;
5373 case ARM::VLD3LNqAsm_16:
5374 Spacing = 2;
5375 return ARM::VLD3LNq16;
5376 case ARM::VLD3LNqAsm_32:
5377 Spacing = 2;
5378 return ARM::VLD3LNq32;
Jim Grosbach04945c42011-12-02 00:35:16 +00005379 }
5380}
5381
Jim Grosbachafad0532011-11-10 23:42:14 +00005382bool ARMAsmParser::
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005383processInstruction(MCInst &Inst,
5384 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5385 switch (Inst.getOpcode()) {
Jim Grosbach94298a92012-01-18 22:46:46 +00005386 // Aliases for alternate PC+imm syntax of LDR instructions.
5387 case ARM::t2LDRpcrel:
5388 Inst.setOpcode(ARM::t2LDRpci);
5389 return true;
5390 case ARM::t2LDRBpcrel:
5391 Inst.setOpcode(ARM::t2LDRBpci);
5392 return true;
5393 case ARM::t2LDRHpcrel:
5394 Inst.setOpcode(ARM::t2LDRHpci);
5395 return true;
5396 case ARM::t2LDRSBpcrel:
5397 Inst.setOpcode(ARM::t2LDRSBpci);
5398 return true;
5399 case ARM::t2LDRSHpcrel:
5400 Inst.setOpcode(ARM::t2LDRSHpci);
5401 return true;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005402 // Handle NEON VST complex aliases.
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005403 case ARM::VST1LNdWB_register_Asm_8:
5404 case ARM::VST1LNdWB_register_Asm_16:
5405 case ARM::VST1LNdWB_register_Asm_32: {
Jim Grosbacheb538222011-12-02 22:34:51 +00005406 MCInst TmpInst;
5407 // Shuffle the operands around so the lane index operand is in the
5408 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005409 unsigned Spacing;
5410 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacheb538222011-12-02 22:34:51 +00005411 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5412 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5413 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5414 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5415 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5416 TmpInst.addOperand(Inst.getOperand(1)); // lane
5417 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5418 TmpInst.addOperand(Inst.getOperand(6));
5419 Inst = TmpInst;
5420 return true;
5421 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005422
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005423 case ARM::VST2LNdWB_register_Asm_8:
5424 case ARM::VST2LNdWB_register_Asm_16:
5425 case ARM::VST2LNdWB_register_Asm_32:
5426 case ARM::VST2LNqWB_register_Asm_16:
5427 case ARM::VST2LNqWB_register_Asm_32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005428 MCInst TmpInst;
5429 // Shuffle the operands around so the lane index operand is in the
5430 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005431 unsigned Spacing;
5432 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005433 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5434 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5435 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5436 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5437 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach2c590522011-12-20 20:46:29 +00005438 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5439 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005440 TmpInst.addOperand(Inst.getOperand(1)); // lane
5441 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5442 TmpInst.addOperand(Inst.getOperand(6));
5443 Inst = TmpInst;
5444 return true;
5445 }
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005446 case ARM::VST1LNdWB_fixed_Asm_8:
5447 case ARM::VST1LNdWB_fixed_Asm_16:
5448 case ARM::VST1LNdWB_fixed_Asm_32: {
Jim Grosbacheb538222011-12-02 22:34:51 +00005449 MCInst TmpInst;
5450 // Shuffle the operands around so the lane index operand is in the
5451 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005452 unsigned Spacing;
5453 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacheb538222011-12-02 22:34:51 +00005454 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5455 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5456 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5457 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5458 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5459 TmpInst.addOperand(Inst.getOperand(1)); // lane
5460 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5461 TmpInst.addOperand(Inst.getOperand(5));
5462 Inst = TmpInst;
5463 return true;
5464 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005465
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005466 case ARM::VST2LNdWB_fixed_Asm_8:
5467 case ARM::VST2LNdWB_fixed_Asm_16:
5468 case ARM::VST2LNdWB_fixed_Asm_32:
5469 case ARM::VST2LNqWB_fixed_Asm_16:
5470 case ARM::VST2LNqWB_fixed_Asm_32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005471 MCInst TmpInst;
5472 // Shuffle the operands around so the lane index operand is in the
5473 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005474 unsigned Spacing;
5475 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005476 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5477 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5478 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5479 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5480 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach2c590522011-12-20 20:46:29 +00005481 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5482 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005483 TmpInst.addOperand(Inst.getOperand(1)); // lane
5484 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5485 TmpInst.addOperand(Inst.getOperand(5));
5486 Inst = TmpInst;
5487 return true;
5488 }
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005489 case ARM::VST1LNdAsm_8:
5490 case ARM::VST1LNdAsm_16:
5491 case ARM::VST1LNdAsm_32: {
Jim Grosbacheb538222011-12-02 22:34:51 +00005492 MCInst TmpInst;
5493 // Shuffle the operands around so the lane index operand is in the
5494 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005495 unsigned Spacing;
5496 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacheb538222011-12-02 22:34:51 +00005497 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5498 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5499 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5500 TmpInst.addOperand(Inst.getOperand(1)); // lane
5501 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5502 TmpInst.addOperand(Inst.getOperand(5));
5503 Inst = TmpInst;
5504 return true;
5505 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005506
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005507 case ARM::VST2LNdAsm_8:
5508 case ARM::VST2LNdAsm_16:
5509 case ARM::VST2LNdAsm_32:
5510 case ARM::VST2LNqAsm_16:
5511 case ARM::VST2LNqAsm_32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005512 MCInst TmpInst;
5513 // Shuffle the operands around so the lane index operand is in the
5514 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005515 unsigned Spacing;
5516 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005517 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5518 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5519 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach2c590522011-12-20 20:46:29 +00005520 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5521 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005522 TmpInst.addOperand(Inst.getOperand(1)); // lane
5523 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5524 TmpInst.addOperand(Inst.getOperand(5));
5525 Inst = TmpInst;
5526 return true;
5527 }
5528 // Handle NEON VLD complex aliases.
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005529 case ARM::VLD1LNdWB_register_Asm_8:
5530 case ARM::VLD1LNdWB_register_Asm_16:
5531 case ARM::VLD1LNdWB_register_Asm_32: {
Jim Grosbachdda976b2011-12-02 22:01:52 +00005532 MCInst TmpInst;
5533 // Shuffle the operands around so the lane index operand is in the
5534 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005535 unsigned Spacing;
5536 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachdda976b2011-12-02 22:01:52 +00005537 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5538 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5539 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5540 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5541 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5542 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5543 TmpInst.addOperand(Inst.getOperand(1)); // lane
5544 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5545 TmpInst.addOperand(Inst.getOperand(6));
5546 Inst = TmpInst;
5547 return true;
5548 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005549
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005550 case ARM::VLD2LNdWB_register_Asm_8:
5551 case ARM::VLD2LNdWB_register_Asm_16:
5552 case ARM::VLD2LNdWB_register_Asm_32:
5553 case ARM::VLD2LNqWB_register_Asm_16:
5554 case ARM::VLD2LNqWB_register_Asm_32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005555 MCInst TmpInst;
5556 // Shuffle the operands around so the lane index operand is in the
5557 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005558 unsigned Spacing;
5559 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005560 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005561 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5562 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005563 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5564 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5565 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5566 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5567 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005568 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5569 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005570 TmpInst.addOperand(Inst.getOperand(1)); // lane
5571 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5572 TmpInst.addOperand(Inst.getOperand(6));
5573 Inst = TmpInst;
5574 return true;
5575 }
5576
Jim Grosbacha8b444b2012-01-23 21:53:26 +00005577 case ARM::VLD3LNdWB_register_Asm_8:
5578 case ARM::VLD3LNdWB_register_Asm_16:
5579 case ARM::VLD3LNdWB_register_Asm_32:
5580 case ARM::VLD3LNqWB_register_Asm_16:
5581 case ARM::VLD3LNqWB_register_Asm_32: {
5582 MCInst TmpInst;
5583 // Shuffle the operands around so the lane index operand is in the
5584 // right place.
5585 unsigned Spacing;
5586 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
5587 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5588 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5589 Spacing));
5590 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5591 Spacing));
5592 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5593 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5594 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5595 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5596 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5597 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5598 Spacing));
5599 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5600 Spacing));
5601 TmpInst.addOperand(Inst.getOperand(1)); // lane
5602 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5603 TmpInst.addOperand(Inst.getOperand(6));
5604 Inst = TmpInst;
5605 return true;
5606 }
5607
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005608 case ARM::VLD1LNdWB_fixed_Asm_8:
5609 case ARM::VLD1LNdWB_fixed_Asm_16:
5610 case ARM::VLD1LNdWB_fixed_Asm_32: {
Jim Grosbachdda976b2011-12-02 22:01:52 +00005611 MCInst TmpInst;
5612 // Shuffle the operands around so the lane index operand is in the
5613 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005614 unsigned Spacing;
5615 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachdda976b2011-12-02 22:01:52 +00005616 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5617 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5618 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5619 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5620 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5621 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5622 TmpInst.addOperand(Inst.getOperand(1)); // lane
5623 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5624 TmpInst.addOperand(Inst.getOperand(5));
5625 Inst = TmpInst;
5626 return true;
5627 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005628
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005629 case ARM::VLD2LNdWB_fixed_Asm_8:
5630 case ARM::VLD2LNdWB_fixed_Asm_16:
5631 case ARM::VLD2LNdWB_fixed_Asm_32:
5632 case ARM::VLD2LNqWB_fixed_Asm_16:
5633 case ARM::VLD2LNqWB_fixed_Asm_32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005634 MCInst TmpInst;
5635 // Shuffle the operands around so the lane index operand is in the
5636 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005637 unsigned Spacing;
5638 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005639 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005640 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5641 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005642 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5643 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5644 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5645 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5646 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005647 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5648 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005649 TmpInst.addOperand(Inst.getOperand(1)); // lane
5650 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5651 TmpInst.addOperand(Inst.getOperand(5));
5652 Inst = TmpInst;
5653 return true;
5654 }
5655
Jim Grosbacha8b444b2012-01-23 21:53:26 +00005656 case ARM::VLD3LNdWB_fixed_Asm_8:
5657 case ARM::VLD3LNdWB_fixed_Asm_16:
5658 case ARM::VLD3LNdWB_fixed_Asm_32:
5659 case ARM::VLD3LNqWB_fixed_Asm_16:
5660 case ARM::VLD3LNqWB_fixed_Asm_32: {
5661 MCInst TmpInst;
5662 // Shuffle the operands around so the lane index operand is in the
5663 // right place.
5664 unsigned Spacing;
5665 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
5666 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5667 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5668 Spacing));
5669 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5670 Spacing));
5671 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5672 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5673 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5674 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5675 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5676 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5677 Spacing));
5678 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5679 Spacing));
5680 TmpInst.addOperand(Inst.getOperand(1)); // lane
5681 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5682 TmpInst.addOperand(Inst.getOperand(5));
5683 Inst = TmpInst;
5684 return true;
5685 }
5686
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005687 case ARM::VLD1LNdAsm_8:
5688 case ARM::VLD1LNdAsm_16:
5689 case ARM::VLD1LNdAsm_32: {
Jim Grosbach04945c42011-12-02 00:35:16 +00005690 MCInst TmpInst;
5691 // Shuffle the operands around so the lane index operand is in the
5692 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005693 unsigned Spacing;
5694 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach04945c42011-12-02 00:35:16 +00005695 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5696 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5697 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5698 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5699 TmpInst.addOperand(Inst.getOperand(1)); // lane
5700 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5701 TmpInst.addOperand(Inst.getOperand(5));
5702 Inst = TmpInst;
5703 return true;
5704 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005705
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00005706 case ARM::VLD2LNdAsm_8:
5707 case ARM::VLD2LNdAsm_16:
5708 case ARM::VLD2LNdAsm_32:
5709 case ARM::VLD2LNqAsm_16:
5710 case ARM::VLD2LNqAsm_32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005711 MCInst TmpInst;
5712 // Shuffle the operands around so the lane index operand is in the
5713 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005714 unsigned Spacing;
5715 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005716 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005717 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5718 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005719 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5720 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5721 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005722 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5723 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005724 TmpInst.addOperand(Inst.getOperand(1)); // lane
5725 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5726 TmpInst.addOperand(Inst.getOperand(5));
5727 Inst = TmpInst;
5728 return true;
5729 }
Jim Grosbacha8b444b2012-01-23 21:53:26 +00005730
5731 case ARM::VLD3LNdAsm_8:
5732 case ARM::VLD3LNdAsm_16:
5733 case ARM::VLD3LNdAsm_32:
5734 case ARM::VLD3LNqAsm_16:
5735 case ARM::VLD3LNqAsm_32: {
5736 MCInst TmpInst;
5737 // Shuffle the operands around so the lane index operand is in the
5738 // right place.
5739 unsigned Spacing;
5740 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
5741 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5742 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5743 Spacing));
5744 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5745 Spacing));
5746 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5747 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5748 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5749 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5750 Spacing));
5751 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5752 Spacing));
5753 TmpInst.addOperand(Inst.getOperand(1)); // lane
5754 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5755 TmpInst.addOperand(Inst.getOperand(5));
5756 Inst = TmpInst;
5757 return true;
5758 }
5759
Jim Grosbach485e5622011-12-13 22:45:11 +00005760 // Handle the Thumb2 mode MOV complex aliases.
Jim Grosbachb3ef7132011-12-21 20:54:00 +00005761 case ARM::t2MOVsr:
5762 case ARM::t2MOVSsr: {
5763 // Which instruction to expand to depends on the CCOut operand and
5764 // whether we're in an IT block if the register operands are low
5765 // registers.
5766 bool isNarrow = false;
5767 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5768 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5769 isARMLowRegister(Inst.getOperand(2).getReg()) &&
5770 Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
5771 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsr))
5772 isNarrow = true;
5773 MCInst TmpInst;
5774 unsigned newOpc;
5775 switch(ARM_AM::getSORegShOp(Inst.getOperand(3).getImm())) {
5776 default: llvm_unreachable("unexpected opcode!");
5777 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRrr : ARM::t2ASRrr; break;
5778 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRrr : ARM::t2LSRrr; break;
5779 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLrr : ARM::t2LSLrr; break;
5780 case ARM_AM::ror: newOpc = isNarrow ? ARM::tROR : ARM::t2RORrr; break;
5781 }
5782 TmpInst.setOpcode(newOpc);
5783 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5784 if (isNarrow)
5785 TmpInst.addOperand(MCOperand::CreateReg(
5786 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
5787 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5788 TmpInst.addOperand(Inst.getOperand(2)); // Rm
5789 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5790 TmpInst.addOperand(Inst.getOperand(5));
5791 if (!isNarrow)
5792 TmpInst.addOperand(MCOperand::CreateReg(
5793 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
5794 Inst = TmpInst;
5795 return true;
5796 }
Jim Grosbach485e5622011-12-13 22:45:11 +00005797 case ARM::t2MOVsi:
5798 case ARM::t2MOVSsi: {
5799 // Which instruction to expand to depends on the CCOut operand and
5800 // whether we're in an IT block if the register operands are low
5801 // registers.
5802 bool isNarrow = false;
5803 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5804 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5805 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
5806 isNarrow = true;
5807 MCInst TmpInst;
5808 unsigned newOpc;
5809 switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
5810 default: llvm_unreachable("unexpected opcode!");
5811 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
5812 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
5813 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
5814 case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
Jim Grosbach8c59bbc2011-12-21 21:04:19 +00005815 case ARM_AM::rrx: isNarrow = false; newOpc = ARM::t2RRX; break;
Jim Grosbach485e5622011-12-13 22:45:11 +00005816 }
5817 unsigned Ammount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
5818 if (Ammount == 32) Ammount = 0;
5819 TmpInst.setOpcode(newOpc);
5820 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5821 if (isNarrow)
5822 TmpInst.addOperand(MCOperand::CreateReg(
5823 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
5824 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbach8c59bbc2011-12-21 21:04:19 +00005825 if (newOpc != ARM::t2RRX)
5826 TmpInst.addOperand(MCOperand::CreateImm(Ammount));
Jim Grosbach485e5622011-12-13 22:45:11 +00005827 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5828 TmpInst.addOperand(Inst.getOperand(4));
5829 if (!isNarrow)
5830 TmpInst.addOperand(MCOperand::CreateReg(
5831 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
5832 Inst = TmpInst;
5833 return true;
5834 }
5835 // Handle the ARM mode MOV complex aliases.
Jim Grosbachabcac562011-11-16 18:31:45 +00005836 case ARM::ASRr:
5837 case ARM::LSRr:
5838 case ARM::LSLr:
5839 case ARM::RORr: {
5840 ARM_AM::ShiftOpc ShiftTy;
5841 switch(Inst.getOpcode()) {
5842 default: llvm_unreachable("unexpected opcode!");
5843 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
5844 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
5845 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
5846 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
5847 }
Jim Grosbachabcac562011-11-16 18:31:45 +00005848 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
5849 MCInst TmpInst;
5850 TmpInst.setOpcode(ARM::MOVsr);
5851 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5852 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5853 TmpInst.addOperand(Inst.getOperand(2)); // Rm
5854 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5855 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5856 TmpInst.addOperand(Inst.getOperand(4));
5857 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5858 Inst = TmpInst;
5859 return true;
5860 }
Jim Grosbachc14871c2011-11-10 19:18:01 +00005861 case ARM::ASRi:
5862 case ARM::LSRi:
5863 case ARM::LSLi:
5864 case ARM::RORi: {
5865 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachc14871c2011-11-10 19:18:01 +00005866 switch(Inst.getOpcode()) {
5867 default: llvm_unreachable("unexpected opcode!");
5868 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
5869 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
5870 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
5871 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
5872 }
5873 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach1a2f9ee2011-11-16 19:05:59 +00005874 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachc14871c2011-11-10 19:18:01 +00005875 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
5876 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach61db5a52011-11-10 16:44:55 +00005877 MCInst TmpInst;
Jim Grosbachc14871c2011-11-10 19:18:01 +00005878 TmpInst.setOpcode(Opc);
Jim Grosbach61db5a52011-11-10 16:44:55 +00005879 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5880 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachc14871c2011-11-10 19:18:01 +00005881 if (Opc == ARM::MOVsi)
5882 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach61db5a52011-11-10 16:44:55 +00005883 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5884 TmpInst.addOperand(Inst.getOperand(4));
5885 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5886 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00005887 return true;
Jim Grosbach61db5a52011-11-10 16:44:55 +00005888 }
Jim Grosbach1a2f9ee2011-11-16 19:05:59 +00005889 case ARM::RRXi: {
5890 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
5891 MCInst TmpInst;
5892 TmpInst.setOpcode(ARM::MOVsi);
5893 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5894 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5895 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5896 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5897 TmpInst.addOperand(Inst.getOperand(3));
5898 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
5899 Inst = TmpInst;
5900 return true;
5901 }
Jim Grosbachd9a9be22011-11-10 23:58:34 +00005902 case ARM::t2LDMIA_UPD: {
5903 // If this is a load of a single register, then we should use
5904 // a post-indexed LDR instruction instead, per the ARM ARM.
5905 if (Inst.getNumOperands() != 5)
5906 return false;
5907 MCInst TmpInst;
5908 TmpInst.setOpcode(ARM::t2LDR_POST);
5909 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5910 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5911 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5912 TmpInst.addOperand(MCOperand::CreateImm(4));
5913 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5914 TmpInst.addOperand(Inst.getOperand(3));
5915 Inst = TmpInst;
5916 return true;
5917 }
5918 case ARM::t2STMDB_UPD: {
5919 // If this is a store of a single register, then we should use
5920 // a pre-indexed STR instruction instead, per the ARM ARM.
5921 if (Inst.getNumOperands() != 5)
5922 return false;
5923 MCInst TmpInst;
5924 TmpInst.setOpcode(ARM::t2STR_PRE);
5925 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5926 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5927 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5928 TmpInst.addOperand(MCOperand::CreateImm(-4));
5929 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5930 TmpInst.addOperand(Inst.getOperand(3));
5931 Inst = TmpInst;
5932 return true;
5933 }
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005934 case ARM::LDMIA_UPD:
5935 // If this is a load of a single register via a 'pop', then we should use
5936 // a post-indexed LDR instruction instead, per the ARM ARM.
5937 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
5938 Inst.getNumOperands() == 5) {
5939 MCInst TmpInst;
5940 TmpInst.setOpcode(ARM::LDR_POST_IMM);
5941 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5942 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5943 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5944 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
5945 TmpInst.addOperand(MCOperand::CreateImm(4));
5946 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5947 TmpInst.addOperand(Inst.getOperand(3));
5948 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00005949 return true;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005950 }
5951 break;
Jim Grosbach27ad83d2011-08-11 18:07:11 +00005952 case ARM::STMDB_UPD:
5953 // If this is a store of a single register via a 'push', then we should use
5954 // a pre-indexed STR instruction instead, per the ARM ARM.
5955 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
5956 Inst.getNumOperands() == 5) {
5957 MCInst TmpInst;
5958 TmpInst.setOpcode(ARM::STR_PRE_IMM);
5959 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5960 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5961 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
5962 TmpInst.addOperand(MCOperand::CreateImm(-4));
5963 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5964 TmpInst.addOperand(Inst.getOperand(3));
5965 Inst = TmpInst;
5966 }
5967 break;
Jim Grosbachec9ba982011-12-05 21:06:26 +00005968 case ARM::t2ADDri12:
5969 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
5970 // mnemonic was used (not "addw"), encoding T3 is preferred.
5971 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
5972 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5973 break;
5974 Inst.setOpcode(ARM::t2ADDri);
5975 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5976 break;
5977 case ARM::t2SUBri12:
5978 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
5979 // mnemonic was used (not "subw"), encoding T3 is preferred.
5980 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
5981 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5982 break;
5983 Inst.setOpcode(ARM::t2SUBri);
5984 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5985 break;
Jim Grosbache9ab47a2011-08-16 23:57:34 +00005986 case ARM::tADDi8:
Jim Grosbach6d606fb2011-08-31 17:07:33 +00005987 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5988 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5989 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5990 // to encoding T1 if <Rd> is omitted."
Jim Grosbachafad0532011-11-10 23:42:14 +00005991 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbache9ab47a2011-08-16 23:57:34 +00005992 Inst.setOpcode(ARM::tADDi3);
Jim Grosbachafad0532011-11-10 23:42:14 +00005993 return true;
5994 }
Jim Grosbache9ab47a2011-08-16 23:57:34 +00005995 break;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00005996 case ARM::tSUBi8:
5997 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5998 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5999 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6000 // to encoding T1 if <Rd> is omitted."
Jim Grosbachafad0532011-11-10 23:42:14 +00006001 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachd0c435c2011-09-16 22:58:42 +00006002 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbachafad0532011-11-10 23:42:14 +00006003 return true;
6004 }
Jim Grosbachd0c435c2011-09-16 22:58:42 +00006005 break;
Jim Grosbache489bab2011-12-05 22:16:39 +00006006 case ARM::t2ADDrr: {
6007 // If the destination and first source operand are the same, and
6008 // there's no setting of the flags, use encoding T2 instead of T3.
6009 // Note that this is only for ADD, not SUB. This mirrors the system
6010 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
6011 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
6012 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbachb8c719c2011-12-05 22:27:04 +00006013 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6014 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbache489bab2011-12-05 22:16:39 +00006015 break;
6016 MCInst TmpInst;
6017 TmpInst.setOpcode(ARM::tADDhirr);
6018 TmpInst.addOperand(Inst.getOperand(0));
6019 TmpInst.addOperand(Inst.getOperand(0));
6020 TmpInst.addOperand(Inst.getOperand(2));
6021 TmpInst.addOperand(Inst.getOperand(3));
6022 TmpInst.addOperand(Inst.getOperand(4));
6023 Inst = TmpInst;
6024 return true;
6025 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00006026 case ARM::tB:
6027 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbachafad0532011-11-10 23:42:14 +00006028 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson29cfe6c2011-09-09 21:48:23 +00006029 Inst.setOpcode(ARM::tBcc);
Jim Grosbachafad0532011-11-10 23:42:14 +00006030 return true;
6031 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00006032 break;
6033 case ARM::t2B:
6034 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbachafad0532011-11-10 23:42:14 +00006035 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson29cfe6c2011-09-09 21:48:23 +00006036 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbachafad0532011-11-10 23:42:14 +00006037 return true;
6038 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00006039 break;
Jim Grosbach99bc8462011-08-31 21:17:31 +00006040 case ARM::t2Bcc:
Jim Grosbacha0d34d32011-09-02 23:22:08 +00006041 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbachafad0532011-11-10 23:42:14 +00006042 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbach99bc8462011-08-31 21:17:31 +00006043 Inst.setOpcode(ARM::t2B);
Jim Grosbachafad0532011-11-10 23:42:14 +00006044 return true;
6045 }
Jim Grosbach99bc8462011-08-31 21:17:31 +00006046 break;
Jim Grosbachcbd4ab12011-08-17 22:57:40 +00006047 case ARM::tBcc:
6048 // If the conditional is AL, we really want tB.
Jim Grosbachafad0532011-11-10 23:42:14 +00006049 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbachcbd4ab12011-08-17 22:57:40 +00006050 Inst.setOpcode(ARM::tB);
Jim Grosbachafad0532011-11-10 23:42:14 +00006051 return true;
6052 }
Jim Grosbach6ddb5682011-08-18 16:08:39 +00006053 break;
Jim Grosbacha31f2232011-09-07 18:05:34 +00006054 case ARM::tLDMIA: {
6055 // If the register list contains any high registers, or if the writeback
6056 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
6057 // instead if we're in Thumb2. Otherwise, this should have generated
6058 // an error in validateInstruction().
6059 unsigned Rn = Inst.getOperand(0).getReg();
6060 bool hasWritebackToken =
6061 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6062 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
6063 bool listContainsBase;
6064 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
6065 (!listContainsBase && !hasWritebackToken) ||
6066 (listContainsBase && hasWritebackToken)) {
6067 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6068 assert (isThumbTwo());
6069 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
6070 // If we're switching to the updating version, we need to insert
6071 // the writeback tied operand.
6072 if (hasWritebackToken)
6073 Inst.insert(Inst.begin(),
6074 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbachafad0532011-11-10 23:42:14 +00006075 return true;
Jim Grosbacha31f2232011-09-07 18:05:34 +00006076 }
6077 break;
6078 }
Jim Grosbach099c9762011-09-16 20:50:13 +00006079 case ARM::tSTMIA_UPD: {
6080 // If the register list contains any high registers, we need to use
6081 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6082 // should have generated an error in validateInstruction().
6083 unsigned Rn = Inst.getOperand(0).getReg();
6084 bool listContainsBase;
6085 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
6086 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6087 assert (isThumbTwo());
6088 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbachafad0532011-11-10 23:42:14 +00006089 return true;
Jim Grosbach099c9762011-09-16 20:50:13 +00006090 }
6091 break;
6092 }
Jim Grosbach9bded9d2011-11-10 23:17:11 +00006093 case ARM::tPOP: {
6094 bool listContainsBase;
6095 // If the register list contains any high registers, we need to use
6096 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6097 // should have generated an error in validateInstruction().
6098 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbachafad0532011-11-10 23:42:14 +00006099 return false;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00006100 assert (isThumbTwo());
6101 Inst.setOpcode(ARM::t2LDMIA_UPD);
6102 // Add the base register and writeback operands.
6103 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6104 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbachafad0532011-11-10 23:42:14 +00006105 return true;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00006106 }
6107 case ARM::tPUSH: {
6108 bool listContainsBase;
6109 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbachafad0532011-11-10 23:42:14 +00006110 return false;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00006111 assert (isThumbTwo());
6112 Inst.setOpcode(ARM::t2STMDB_UPD);
6113 // Add the base register and writeback operands.
6114 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6115 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbachafad0532011-11-10 23:42:14 +00006116 return true;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00006117 }
Jim Grosbachb908b7a2011-09-10 00:15:36 +00006118 case ARM::t2MOVi: {
6119 // If we can use the 16-bit encoding and the user didn't explicitly
6120 // request the 32-bit variant, transform it here.
6121 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6122 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbach18b8b172011-09-14 19:12:11 +00006123 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
6124 Inst.getOperand(4).getReg() == ARM::CPSR) ||
6125 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbachb908b7a2011-09-10 00:15:36 +00006126 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6127 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6128 // The operands aren't in the same order for tMOVi8...
6129 MCInst TmpInst;
6130 TmpInst.setOpcode(ARM::tMOVi8);
6131 TmpInst.addOperand(Inst.getOperand(0));
6132 TmpInst.addOperand(Inst.getOperand(4));
6133 TmpInst.addOperand(Inst.getOperand(1));
6134 TmpInst.addOperand(Inst.getOperand(2));
6135 TmpInst.addOperand(Inst.getOperand(3));
6136 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00006137 return true;
Jim Grosbachb908b7a2011-09-10 00:15:36 +00006138 }
6139 break;
6140 }
6141 case ARM::t2MOVr: {
6142 // If we can use the 16-bit encoding and the user didn't explicitly
6143 // request the 32-bit variant, transform it here.
6144 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6145 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6146 Inst.getOperand(2).getImm() == ARMCC::AL &&
6147 Inst.getOperand(4).getReg() == ARM::CPSR &&
6148 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6149 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6150 // The operands aren't the same for tMOV[S]r... (no cc_out)
6151 MCInst TmpInst;
6152 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
6153 TmpInst.addOperand(Inst.getOperand(0));
6154 TmpInst.addOperand(Inst.getOperand(1));
6155 TmpInst.addOperand(Inst.getOperand(2));
6156 TmpInst.addOperand(Inst.getOperand(3));
6157 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00006158 return true;
Jim Grosbachb908b7a2011-09-10 00:15:36 +00006159 }
6160 break;
6161 }
Jim Grosbach82213192011-09-19 20:29:33 +00006162 case ARM::t2SXTH:
Jim Grosbachb3519802011-09-20 00:46:54 +00006163 case ARM::t2SXTB:
6164 case ARM::t2UXTH:
6165 case ARM::t2UXTB: {
Jim Grosbach82213192011-09-19 20:29:33 +00006166 // If we can use the 16-bit encoding and the user didn't explicitly
6167 // request the 32-bit variant, transform it here.
6168 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6169 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6170 Inst.getOperand(2).getImm() == 0 &&
6171 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6172 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbachb3519802011-09-20 00:46:54 +00006173 unsigned NewOpc;
6174 switch (Inst.getOpcode()) {
6175 default: llvm_unreachable("Illegal opcode!");
6176 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
6177 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
6178 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
6179 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
6180 }
Jim Grosbach82213192011-09-19 20:29:33 +00006181 // The operands aren't the same for thumb1 (no rotate operand).
6182 MCInst TmpInst;
6183 TmpInst.setOpcode(NewOpc);
6184 TmpInst.addOperand(Inst.getOperand(0));
6185 TmpInst.addOperand(Inst.getOperand(1));
6186 TmpInst.addOperand(Inst.getOperand(3));
6187 TmpInst.addOperand(Inst.getOperand(4));
6188 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00006189 return true;
Jim Grosbach82213192011-09-19 20:29:33 +00006190 }
6191 break;
6192 }
Jim Grosbache2ca9e52011-12-20 00:59:38 +00006193 case ARM::MOVsi: {
6194 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm());
6195 if (SOpc == ARM_AM::rrx) return false;
6196 if (ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()) == 0) {
6197 // Shifting by zero is accepted as a vanilla 'MOVr'
6198 MCInst TmpInst;
6199 TmpInst.setOpcode(ARM::MOVr);
6200 TmpInst.addOperand(Inst.getOperand(0));
6201 TmpInst.addOperand(Inst.getOperand(1));
6202 TmpInst.addOperand(Inst.getOperand(3));
6203 TmpInst.addOperand(Inst.getOperand(4));
6204 TmpInst.addOperand(Inst.getOperand(5));
6205 Inst = TmpInst;
6206 return true;
6207 }
6208 return false;
6209 }
Jim Grosbach12ccf452011-12-22 18:04:04 +00006210 case ARM::ANDrsi:
6211 case ARM::ORRrsi:
6212 case ARM::EORrsi:
6213 case ARM::BICrsi:
6214 case ARM::SUBrsi:
6215 case ARM::ADDrsi: {
6216 unsigned newOpc;
6217 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(3).getImm());
6218 if (SOpc == ARM_AM::rrx) return false;
6219 switch (Inst.getOpcode()) {
Matt Beaumont-Gayb982d8e2012-01-03 19:03:59 +00006220 default: assert(0 && "unexpected opcode!");
Jim Grosbach12ccf452011-12-22 18:04:04 +00006221 case ARM::ANDrsi: newOpc = ARM::ANDrr; break;
6222 case ARM::ORRrsi: newOpc = ARM::ORRrr; break;
6223 case ARM::EORrsi: newOpc = ARM::EORrr; break;
6224 case ARM::BICrsi: newOpc = ARM::BICrr; break;
6225 case ARM::SUBrsi: newOpc = ARM::SUBrr; break;
6226 case ARM::ADDrsi: newOpc = ARM::ADDrr; break;
6227 }
6228 // If the shift is by zero, use the non-shifted instruction definition.
6229 if (ARM_AM::getSORegOffset(Inst.getOperand(3).getImm()) == 0) {
6230 MCInst TmpInst;
6231 TmpInst.setOpcode(newOpc);
6232 TmpInst.addOperand(Inst.getOperand(0));
6233 TmpInst.addOperand(Inst.getOperand(1));
6234 TmpInst.addOperand(Inst.getOperand(2));
6235 TmpInst.addOperand(Inst.getOperand(4));
6236 TmpInst.addOperand(Inst.getOperand(5));
6237 TmpInst.addOperand(Inst.getOperand(6));
6238 Inst = TmpInst;
6239 return true;
6240 }
6241 return false;
6242 }
Jim Grosbach3d1eac82011-08-26 21:43:41 +00006243 case ARM::t2IT: {
6244 // The mask bits for all but the first condition are represented as
6245 // the low bit of the condition code value implies 't'. We currently
6246 // always have 1 implies 't', so XOR toggle the bits if the low bit
6247 // of the condition code is zero. The encoding also expects the low
6248 // bit of the condition to be encoded as bit 4 of the mask operand,
6249 // so mask that in if needed
6250 MCOperand &MO = Inst.getOperand(1);
6251 unsigned Mask = MO.getImm();
Jim Grosbached16ec42011-08-29 22:24:09 +00006252 unsigned OrigMask = Mask;
6253 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00006254 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach3d1eac82011-08-26 21:43:41 +00006255 assert(Mask && TZ <= 3 && "illegal IT mask value!");
6256 for (unsigned i = 3; i != TZ; --i)
6257 Mask ^= 1 << i;
6258 } else
6259 Mask |= 0x10;
6260 MO.setImm(Mask);
Jim Grosbached16ec42011-08-29 22:24:09 +00006261
6262 // Set up the IT block state according to the IT instruction we just
6263 // matched.
6264 assert(!inITBlock() && "nested IT blocks?!");
6265 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
6266 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
6267 ITState.CurPosition = 0;
6268 ITState.FirstCond = true;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00006269 break;
6270 }
Jim Grosbach8ba76c62011-08-11 17:35:48 +00006271 }
Jim Grosbachafad0532011-11-10 23:42:14 +00006272 return false;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00006273}
6274
Jim Grosbach3e941ae2011-08-16 20:45:50 +00006275unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
6276 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
6277 // suffix depending on whether they're in an IT block or not.
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00006278 unsigned Opc = Inst.getOpcode();
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00006279 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach3e941ae2011-08-16 20:45:50 +00006280 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
6281 assert(MCID.hasOptionalDef() &&
6282 "optionally flag setting instruction missing optional def operand");
6283 assert(MCID.NumOperands == Inst.getNumOperands() &&
6284 "operand count mismatch!");
6285 // Find the optional-def operand (cc_out).
6286 unsigned OpNo;
6287 for (OpNo = 0;
6288 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
6289 ++OpNo)
6290 ;
6291 // If we're parsing Thumb1, reject it completely.
6292 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
6293 return Match_MnemonicFail;
6294 // If we're parsing Thumb2, which form is legal depends on whether we're
6295 // in an IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00006296 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
6297 !inITBlock())
Jim Grosbach3e941ae2011-08-16 20:45:50 +00006298 return Match_RequiresITBlock;
Jim Grosbached16ec42011-08-29 22:24:09 +00006299 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
6300 inITBlock())
6301 return Match_RequiresNotITBlock;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00006302 }
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00006303 // Some high-register supporting Thumb1 encodings only allow both registers
6304 // to be from r0-r7 when in Thumb2.
6305 else if (Opc == ARM::tADDhirr && isThumbOne() &&
6306 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6307 isARMLowRegister(Inst.getOperand(2).getReg()))
6308 return Match_RequiresThumb2;
6309 // Others only require ARMv6 or later.
Jim Grosbachf86cd372011-08-19 20:46:54 +00006310 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00006311 isARMLowRegister(Inst.getOperand(0).getReg()) &&
6312 isARMLowRegister(Inst.getOperand(1).getReg()))
6313 return Match_RequiresV6;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00006314 return Match_Success;
6315}
6316
Chris Lattner9487de62010-10-28 21:28:01 +00006317bool ARMAsmParser::
6318MatchAndEmitInstruction(SMLoc IDLoc,
6319 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
6320 MCStreamer &Out) {
6321 MCInst Inst;
6322 unsigned ErrorInfo;
Jim Grosbach120a96a2011-08-15 23:03:29 +00006323 unsigned MatchResult;
Kevin Enderby3164a342010-12-09 19:19:43 +00006324 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby3164a342010-12-09 19:19:43 +00006325 switch (MatchResult) {
Jim Grosbach120a96a2011-08-15 23:03:29 +00006326 default: break;
Chris Lattnerd27b05e2010-10-28 21:41:58 +00006327 case Match_Success:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00006328 // Context sensitive operand constraints aren't handled by the matcher,
6329 // so check them here.
Jim Grosbacha0d34d32011-09-02 23:22:08 +00006330 if (validateInstruction(Inst, Operands)) {
6331 // Still progress the IT block, otherwise one wrong condition causes
6332 // nasty cascading errors.
6333 forwardITPosition();
Jim Grosbachedaa35a2011-07-26 18:25:39 +00006334 return true;
Jim Grosbacha0d34d32011-09-02 23:22:08 +00006335 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00006336
Jim Grosbach8ba76c62011-08-11 17:35:48 +00006337 // Some instructions need post-processing to, for example, tweak which
Jim Grosbachafad0532011-11-10 23:42:14 +00006338 // encoding is selected. Loop on it while changes happen so the
6339 // individual transformations can chain off each other. E.g.,
6340 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
6341 while (processInstruction(Inst, Operands))
6342 ;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00006343
Jim Grosbacha0d34d32011-09-02 23:22:08 +00006344 // Only move forward at the very end so that everything in validate
6345 // and process gets a consistent answer about whether we're in an IT
6346 // block.
6347 forwardITPosition();
6348
Chris Lattner9487de62010-10-28 21:28:01 +00006349 Out.EmitInstruction(Inst);
6350 return false;
Chris Lattnerd27b05e2010-10-28 21:41:58 +00006351 case Match_MissingFeature:
6352 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
6353 return true;
6354 case Match_InvalidOperand: {
6355 SMLoc ErrorLoc = IDLoc;
6356 if (ErrorInfo != ~0U) {
6357 if (ErrorInfo >= Operands.size())
6358 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach624bcc72010-10-29 14:46:02 +00006359
Chris Lattnerd27b05e2010-10-28 21:41:58 +00006360 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
6361 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
6362 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00006363
Chris Lattnerd27b05e2010-10-28 21:41:58 +00006364 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattner9487de62010-10-28 21:28:01 +00006365 }
Chris Lattnerd27b05e2010-10-28 21:41:58 +00006366 case Match_MnemonicFail:
Jim Grosbach3e941ae2011-08-16 20:45:50 +00006367 return Error(IDLoc, "invalid instruction");
Daniel Dunbar66193402011-02-04 17:12:23 +00006368 case Match_ConversionFail:
Jim Grosbach8e048492011-08-19 22:07:46 +00006369 // The converter function will have already emited a diagnostic.
6370 return true;
Jim Grosbached16ec42011-08-29 22:24:09 +00006371 case Match_RequiresNotITBlock:
6372 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach3e941ae2011-08-16 20:45:50 +00006373 case Match_RequiresITBlock:
6374 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00006375 case Match_RequiresV6:
6376 return Error(IDLoc, "instruction variant requires ARMv6 or later");
6377 case Match_RequiresThumb2:
6378 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnerd27b05e2010-10-28 21:41:58 +00006379 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00006380
Eric Christopher91d7b902010-10-29 09:26:59 +00006381 llvm_unreachable("Implement any new match types added!");
Chris Lattner9487de62010-10-28 21:28:01 +00006382}
6383
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006384/// parseDirective parses the arm specific directives
Kevin Enderbyccab3172009-09-15 00:27:25 +00006385bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
6386 StringRef IDVal = DirectiveID.getIdentifier();
6387 if (IDVal == ".word")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006388 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00006389 else if (IDVal == ".thumb")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006390 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach7f882392011-12-07 18:04:19 +00006391 else if (IDVal == ".arm")
6392 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00006393 else if (IDVal == ".thumb_func")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006394 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00006395 else if (IDVal == ".code")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006396 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00006397 else if (IDVal == ".syntax")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006398 return parseDirectiveSyntax(DirectiveID.getLoc());
Jim Grosbachab5830e2011-12-14 02:16:11 +00006399 else if (IDVal == ".unreq")
6400 return parseDirectiveUnreq(DirectiveID.getLoc());
Jason W Kim135d2442011-12-20 17:38:12 +00006401 else if (IDVal == ".arch")
6402 return parseDirectiveArch(DirectiveID.getLoc());
6403 else if (IDVal == ".eabi_attribute")
6404 return parseDirectiveEabiAttr(DirectiveID.getLoc());
Kevin Enderbyccab3172009-09-15 00:27:25 +00006405 return true;
6406}
6407
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006408/// parseDirectiveWord
Kevin Enderbyccab3172009-09-15 00:27:25 +00006409/// ::= .word [ expression (, expression)* ]
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006410bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyccab3172009-09-15 00:27:25 +00006411 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6412 for (;;) {
6413 const MCExpr *Value;
6414 if (getParser().ParseExpression(Value))
6415 return true;
6416
Chris Lattnerc35681b2010-01-19 19:46:13 +00006417 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyccab3172009-09-15 00:27:25 +00006418
6419 if (getLexer().is(AsmToken::EndOfStatement))
6420 break;
Jim Grosbach624bcc72010-10-29 14:46:02 +00006421
Kevin Enderbyccab3172009-09-15 00:27:25 +00006422 // FIXME: Improve diagnostic.
6423 if (getLexer().isNot(AsmToken::Comma))
6424 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00006425 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00006426 }
6427 }
6428
Sean Callanana83fd7d2010-01-19 20:27:46 +00006429 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00006430 return false;
6431}
6432
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006433/// parseDirectiveThumb
Kevin Enderby146dcf22009-10-15 20:48:48 +00006434/// ::= .thumb
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006435bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby146dcf22009-10-15 20:48:48 +00006436 if (getLexer().isNot(AsmToken::EndOfStatement))
6437 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00006438 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006439
Jim Grosbach7f882392011-12-07 18:04:19 +00006440 if (!isThumb())
6441 SwitchMode();
6442 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
6443 return false;
6444}
6445
6446/// parseDirectiveARM
6447/// ::= .arm
6448bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
6449 if (getLexer().isNot(AsmToken::EndOfStatement))
6450 return Error(L, "unexpected token in directive");
6451 Parser.Lex();
6452
6453 if (isThumb())
6454 SwitchMode();
6455 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby146dcf22009-10-15 20:48:48 +00006456 return false;
6457}
6458
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006459/// parseDirectiveThumbFunc
Kevin Enderby146dcf22009-10-15 20:48:48 +00006460/// ::= .thumbfunc symbol_name
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006461bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00006462 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
6463 bool isMachO = MAI.hasSubsectionsViaSymbols();
6464 StringRef Name;
Jim Grosbach1152cc02011-12-21 22:30:16 +00006465 bool needFuncName = true;
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00006466
Jim Grosbach1152cc02011-12-21 22:30:16 +00006467 // Darwin asm has (optionally) function name after .thumb_func direction
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00006468 // ELF doesn't
6469 if (isMachO) {
6470 const AsmToken &Tok = Parser.getTok();
Jim Grosbach1152cc02011-12-21 22:30:16 +00006471 if (Tok.isNot(AsmToken::EndOfStatement)) {
6472 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
6473 return Error(L, "unexpected token in .thumb_func directive");
6474 Name = Tok.getIdentifier();
6475 Parser.Lex(); // Consume the identifier token.
6476 needFuncName = false;
6477 }
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00006478 }
6479
Jim Grosbach1152cc02011-12-21 22:30:16 +00006480 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby146dcf22009-10-15 20:48:48 +00006481 return Error(L, "unexpected token in directive");
Jim Grosbach1152cc02011-12-21 22:30:16 +00006482
6483 // Eat the end of statement and any blank lines that follow.
6484 while (getLexer().is(AsmToken::EndOfStatement))
6485 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006486
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00006487 // FIXME: assuming function name will be the line following .thumb_func
Jim Grosbach1152cc02011-12-21 22:30:16 +00006488 // We really should be checking the next symbol definition even if there's
6489 // stuff in between.
6490 if (needFuncName) {
Jim Grosbach42ba6282011-11-10 20:48:53 +00006491 Name = Parser.getTok().getIdentifier();
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00006492 }
6493
Jim Grosbachc6db8ce2010-11-05 22:33:53 +00006494 // Mark symbol as a thumb symbol.
6495 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
6496 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby146dcf22009-10-15 20:48:48 +00006497 return false;
6498}
6499
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006500/// parseDirectiveSyntax
Kevin Enderby146dcf22009-10-15 20:48:48 +00006501/// ::= .syntax unified | divided
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006502bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00006503 const AsmToken &Tok = Parser.getTok();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006504 if (Tok.isNot(AsmToken::Identifier))
6505 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer92d89982010-07-14 22:38:02 +00006506 StringRef Mode = Tok.getString();
Duncan Sands257eba42010-06-29 13:04:35 +00006507 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callanana83fd7d2010-01-19 20:27:46 +00006508 Parser.Lex();
Duncan Sands257eba42010-06-29 13:04:35 +00006509 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderbye9f2f0c2011-01-27 23:22:36 +00006510 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby146dcf22009-10-15 20:48:48 +00006511 else
6512 return Error(L, "unrecognized syntax mode in .syntax directive");
6513
6514 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan936b0d32010-01-19 21:44:56 +00006515 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00006516 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006517
6518 // TODO tell the MC streamer the mode
6519 // getParser().getStreamer().Emit???();
6520 return false;
6521}
6522
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006523/// parseDirectiveCode
Kevin Enderby146dcf22009-10-15 20:48:48 +00006524/// ::= .code 16 | 32
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006525bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00006526 const AsmToken &Tok = Parser.getTok();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006527 if (Tok.isNot(AsmToken::Integer))
6528 return Error(L, "unexpected token in .code directive");
Sean Callanan936b0d32010-01-19 21:44:56 +00006529 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands257eba42010-06-29 13:04:35 +00006530 if (Val == 16)
Sean Callanana83fd7d2010-01-19 20:27:46 +00006531 Parser.Lex();
Duncan Sands257eba42010-06-29 13:04:35 +00006532 else if (Val == 32)
Sean Callanana83fd7d2010-01-19 20:27:46 +00006533 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006534 else
6535 return Error(L, "invalid operand to .code directive");
6536
6537 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan936b0d32010-01-19 21:44:56 +00006538 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00006539 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006540
Evan Cheng284b4672011-07-08 22:36:29 +00006541 if (Val == 16) {
Jim Grosbachf471ac32011-09-06 18:46:23 +00006542 if (!isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00006543 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00006544 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng284b4672011-07-08 22:36:29 +00006545 } else {
Jim Grosbachf471ac32011-09-06 18:46:23 +00006546 if (isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00006547 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00006548 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Cheng45543ba2011-07-08 22:49:55 +00006549 }
Jim Grosbach2db0ea02010-11-05 22:40:53 +00006550
Kevin Enderby146dcf22009-10-15 20:48:48 +00006551 return false;
6552}
6553
Jim Grosbachab5830e2011-12-14 02:16:11 +00006554/// parseDirectiveReq
6555/// ::= name .req registername
6556bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
6557 Parser.Lex(); // Eat the '.req' token.
6558 unsigned Reg;
6559 SMLoc SRegLoc, ERegLoc;
6560 if (ParseRegister(Reg, SRegLoc, ERegLoc)) {
6561 Parser.EatToEndOfStatement();
6562 return Error(SRegLoc, "register name expected");
6563 }
6564
6565 // Shouldn't be anything else.
6566 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
6567 Parser.EatToEndOfStatement();
6568 return Error(Parser.getTok().getLoc(),
6569 "unexpected input in .req directive.");
6570 }
6571
6572 Parser.Lex(); // Consume the EndOfStatement
6573
6574 if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg)
6575 return Error(SRegLoc, "redefinition of '" + Name +
6576 "' does not match original.");
6577
6578 return false;
6579}
6580
6581/// parseDirectiveUneq
6582/// ::= .unreq registername
6583bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
6584 if (Parser.getTok().isNot(AsmToken::Identifier)) {
6585 Parser.EatToEndOfStatement();
6586 return Error(L, "unexpected input in .unreq directive.");
6587 }
6588 RegisterReqs.erase(Parser.getTok().getIdentifier());
6589 Parser.Lex(); // Eat the identifier.
6590 return false;
6591}
6592
Jason W Kim135d2442011-12-20 17:38:12 +00006593/// parseDirectiveArch
6594/// ::= .arch token
6595bool ARMAsmParser::parseDirectiveArch(SMLoc L) {
6596 return true;
6597}
6598
6599/// parseDirectiveEabiAttr
6600/// ::= .eabi_attribute int, int
6601bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
6602 return true;
6603}
6604
Sean Callanan643a5572010-04-07 20:29:34 +00006605extern "C" void LLVMInitializeARMAsmLexer();
6606
Kevin Enderby8be42bd2009-10-30 22:55:57 +00006607/// Force static initialization.
Kevin Enderbyccab3172009-09-15 00:27:25 +00006608extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng11424442011-07-26 00:24:13 +00006609 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
6610 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan643a5572010-04-07 20:29:34 +00006611 LLVMInitializeARMAsmLexer();
Kevin Enderbyccab3172009-09-15 00:27:25 +00006612}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00006613
Chris Lattner3e4582a2010-09-06 19:11:01 +00006614#define GET_REGISTER_MATCHER
6615#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00006616#include "ARMGenAsmMatcher.inc"