blob: a520bfff6d30ed7f79c7b6c7c659711a1bf77dd0 [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 Grosbachd0637bf2011-10-07 23:56:00 +00001171 bool isVectorIndex8() const {
1172 if (Kind != k_VectorIndex) return false;
1173 return VectorIndex.Val < 8;
1174 }
1175 bool isVectorIndex16() const {
1176 if (Kind != k_VectorIndex) return false;
1177 return VectorIndex.Val < 4;
1178 }
1179 bool isVectorIndex32() const {
1180 if (Kind != k_VectorIndex) return false;
1181 return VectorIndex.Val < 2;
1182 }
1183
Jim Grosbach741cd732011-10-17 22:26:03 +00001184 bool isNEONi8splat() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001185 if (!isImm()) return false;
Jim Grosbach741cd732011-10-17 22:26:03 +00001186 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1187 // Must be a constant.
1188 if (!CE) return false;
1189 int64_t Value = CE->getValue();
1190 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1191 // value.
Jim Grosbach741cd732011-10-17 22:26:03 +00001192 return Value >= 0 && Value < 256;
1193 }
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001194
Jim Grosbachcda32ae2011-10-17 23:09:09 +00001195 bool isNEONi16splat() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001196 if (!isImm()) return false;
Jim Grosbachcda32ae2011-10-17 23:09:09 +00001197 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1198 // Must be a constant.
1199 if (!CE) return false;
1200 int64_t Value = CE->getValue();
1201 // i16 value in the range [0,255] or [0x0100, 0xff00]
1202 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1203 }
1204
Jim Grosbach8211c052011-10-18 00:22:00 +00001205 bool isNEONi32splat() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001206 if (!isImm()) return false;
Jim Grosbach8211c052011-10-18 00:22:00 +00001207 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1208 // Must be a constant.
1209 if (!CE) return false;
1210 int64_t Value = CE->getValue();
1211 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1212 return (Value >= 0 && Value < 256) ||
1213 (Value >= 0x0100 && Value <= 0xff00) ||
1214 (Value >= 0x010000 && Value <= 0xff0000) ||
1215 (Value >= 0x01000000 && Value <= 0xff000000);
1216 }
1217
1218 bool isNEONi32vmov() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001219 if (!isImm()) return false;
Jim Grosbach8211c052011-10-18 00:22:00 +00001220 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1221 // Must be a constant.
1222 if (!CE) return false;
1223 int64_t Value = CE->getValue();
1224 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1225 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1226 return (Value >= 0 && Value < 256) ||
1227 (Value >= 0x0100 && Value <= 0xff00) ||
1228 (Value >= 0x010000 && Value <= 0xff0000) ||
1229 (Value >= 0x01000000 && Value <= 0xff000000) ||
1230 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1231 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1232 }
Jim Grosbach045b6c72011-12-19 23:51:07 +00001233 bool isNEONi32vmovNeg() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001234 if (!isImm()) return false;
Jim Grosbach045b6c72011-12-19 23:51:07 +00001235 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1236 // Must be a constant.
1237 if (!CE) return false;
1238 int64_t Value = ~CE->getValue();
1239 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1240 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1241 return (Value >= 0 && Value < 256) ||
1242 (Value >= 0x0100 && Value <= 0xff00) ||
1243 (Value >= 0x010000 && Value <= 0xff0000) ||
1244 (Value >= 0x01000000 && Value <= 0xff000000) ||
1245 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1246 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1247 }
Jim Grosbach8211c052011-10-18 00:22:00 +00001248
Jim Grosbache4454e02011-10-18 16:18:11 +00001249 bool isNEONi64splat() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001250 if (!isImm()) return false;
Jim Grosbache4454e02011-10-18 16:18:11 +00001251 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1252 // Must be a constant.
1253 if (!CE) return false;
1254 uint64_t Value = CE->getValue();
1255 // i64 value with each byte being either 0 or 0xff.
1256 for (unsigned i = 0; i < 8; ++i)
1257 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1258 return true;
1259 }
1260
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001261 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner5d6f6a02010-10-29 00:27:31 +00001262 // Add as immediates when possible. Null MCExpr = 0.
1263 if (Expr == 0)
1264 Inst.addOperand(MCOperand::CreateImm(0));
1265 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001266 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1267 else
1268 Inst.addOperand(MCOperand::CreateExpr(Expr));
1269 }
1270
Daniel Dunbard8042b72010-08-11 06:36:53 +00001271 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001272 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbard8042b72010-08-11 06:36:53 +00001273 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach968c9272010-12-06 18:30:57 +00001274 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1275 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbard8042b72010-08-11 06:36:53 +00001276 }
1277
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001278 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1279 assert(N == 1 && "Invalid number of operands!");
1280 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1281 }
1282
Jim Grosbach48399582011-10-12 17:34:41 +00001283 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1284 assert(N == 1 && "Invalid number of operands!");
1285 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1286 }
1287
1288 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1289 assert(N == 1 && "Invalid number of operands!");
1290 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1291 }
1292
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001293 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1294 assert(N == 1 && "Invalid number of operands!");
1295 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1296 }
1297
1298 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1299 assert(N == 1 && "Invalid number of operands!");
1300 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1301 }
1302
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001303 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1304 assert(N == 1 && "Invalid number of operands!");
1305 Inst.addOperand(MCOperand::CreateReg(getReg()));
1306 }
1307
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001308 void addRegOperands(MCInst &Inst, unsigned N) const {
1309 assert(N == 1 && "Invalid number of operands!");
1310 Inst.addOperand(MCOperand::CreateReg(getReg()));
1311 }
1312
Jim Grosbachac798e12011-07-25 20:49:51 +00001313 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001314 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001315 assert(isRegShiftedReg() &&
1316 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachac798e12011-07-25 20:49:51 +00001317 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1318 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001319 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachac798e12011-07-25 20:49:51 +00001320 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001321 }
1322
Jim Grosbachac798e12011-07-25 20:49:51 +00001323 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson04912702011-07-21 23:38:37 +00001324 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001325 assert(isRegShiftedImm() &&
1326 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachac798e12011-07-25 20:49:51 +00001327 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Andersonb595ed02011-07-21 18:54:16 +00001328 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachac798e12011-07-25 20:49:51 +00001329 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Andersonb595ed02011-07-21 18:54:16 +00001330 }
1331
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001332 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001333 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001334 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1335 ShifterImm.Imm));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001336 }
1337
Bill Wendling8d2aa032010-11-08 23:49:57 +00001338 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling2cae3272010-11-09 22:44:22 +00001339 assert(N == 1 && "Invalid number of operands!");
Bill Wendlingbed94652010-11-09 23:28:44 +00001340 const SmallVectorImpl<unsigned> &RegList = getRegList();
1341 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00001342 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1343 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling8d2aa032010-11-08 23:49:57 +00001344 }
1345
Bill Wendling9898ac92010-11-17 04:32:08 +00001346 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1347 addRegListOperands(Inst, N);
1348 }
1349
1350 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1351 addRegListOperands(Inst, N);
1352 }
1353
Jim Grosbach833b9d32011-07-27 20:15:40 +00001354 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1355 assert(N == 1 && "Invalid number of operands!");
1356 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1357 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1358 }
1359
Jim Grosbach864b6092011-07-28 21:34:26 +00001360 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1361 assert(N == 1 && "Invalid number of operands!");
1362 // Munge the lsb/width into a bitfield mask.
1363 unsigned lsb = Bitfield.LSB;
1364 unsigned width = Bitfield.Width;
1365 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1366 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1367 (32 - (lsb + width)));
1368 Inst.addOperand(MCOperand::CreateImm(Mask));
1369 }
1370
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001371 void addImmOperands(MCInst &Inst, unsigned N) const {
1372 assert(N == 1 && "Invalid number of operands!");
1373 addExpr(Inst, getImm());
1374 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00001375
Jim Grosbachea231912011-12-22 22:19:05 +00001376 void addFBits16Operands(MCInst &Inst, unsigned N) const {
1377 assert(N == 1 && "Invalid number of operands!");
1378 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1379 Inst.addOperand(MCOperand::CreateImm(16 - CE->getValue()));
1380 }
1381
1382 void addFBits32Operands(MCInst &Inst, unsigned N) const {
1383 assert(N == 1 && "Invalid number of operands!");
1384 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1385 Inst.addOperand(MCOperand::CreateImm(32 - CE->getValue()));
1386 }
1387
Jim Grosbache7fbce72011-10-03 23:38:36 +00001388 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1389 assert(N == 1 && "Invalid number of operands!");
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00001390 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1391 int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
1392 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbache7fbce72011-10-03 23:38:36 +00001393 }
1394
Jim Grosbach7db8d692011-09-08 22:07:06 +00001395 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1396 assert(N == 1 && "Invalid number of operands!");
1397 // FIXME: We really want to scale the value here, but the LDRD/STRD
1398 // instruction don't encode operands that way yet.
1399 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1400 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1401 }
1402
Jim Grosbach0a0b3072011-08-24 21:22:15 +00001403 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1404 assert(N == 1 && "Invalid number of operands!");
1405 // The immediate is scaled by four in the encoding and is stored
1406 // in the MCInst as such. Lop off the low two bits here.
1407 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1408 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1409 }
1410
1411 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1412 assert(N == 1 && "Invalid number of operands!");
1413 // The immediate is scaled by four in the encoding and is stored
1414 // in the MCInst as such. Lop off the low two bits here.
1415 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1416 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1417 }
1418
Jim Grosbach475c6db2011-07-25 23:09:14 +00001419 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1420 assert(N == 1 && "Invalid number of operands!");
1421 // The constant encodes as the immediate-1, and we store in the instruction
1422 // the bits as encoded, so subtract off one here.
1423 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1424 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1425 }
1426
Jim Grosbach801e0a32011-07-22 23:16:18 +00001427 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1428 assert(N == 1 && "Invalid number of operands!");
1429 // The constant encodes as the immediate-1, and we store in the instruction
1430 // the bits as encoded, so subtract off one here.
1431 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1432 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1433 }
1434
Jim Grosbach46dd4132011-08-17 21:51:27 +00001435 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1436 assert(N == 1 && "Invalid number of operands!");
1437 // The constant encodes as the immediate, except for 32, which encodes as
1438 // zero.
1439 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1440 unsigned Imm = CE->getValue();
1441 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1442 }
1443
Jim Grosbach27c1e252011-07-21 17:23:04 +00001444 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1445 assert(N == 1 && "Invalid number of operands!");
1446 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1447 // the instruction as well.
1448 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1449 int Val = CE->getValue();
1450 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1451 }
1452
Jim Grosbachb009a872011-10-28 22:36:30 +00001453 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1454 assert(N == 1 && "Invalid number of operands!");
1455 // The operand is actually a t2_so_imm, but we have its bitwise
1456 // negation in the assembly source, so twiddle it here.
1457 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1458 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1459 }
1460
Jim Grosbach30506252011-12-08 00:31:07 +00001461 void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1462 assert(N == 1 && "Invalid number of operands!");
1463 // The operand is actually a t2_so_imm, but we have its
1464 // negation in the assembly source, so twiddle it here.
1465 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1466 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1467 }
1468
Jim Grosbach3d785ed2011-10-28 22:50:54 +00001469 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1470 assert(N == 1 && "Invalid number of operands!");
1471 // The operand is actually a so_imm, but we have its bitwise
1472 // negation in the assembly source, so twiddle it here.
1473 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1474 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1475 }
1476
Jim Grosbach30506252011-12-08 00:31:07 +00001477 void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
1478 assert(N == 1 && "Invalid number of operands!");
1479 // The operand is actually a so_imm, but we have its
1480 // negation in the assembly source, so twiddle it here.
1481 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1482 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1483 }
1484
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001485 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1486 assert(N == 1 && "Invalid number of operands!");
1487 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1488 }
1489
Jim Grosbachd3595712011-08-03 23:50:40 +00001490 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1491 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001492 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopesf170f8b2011-03-24 21:04:58 +00001493 }
1494
Jim Grosbach94298a92012-01-18 22:46:46 +00001495 void addMemPCRelImm12Operands(MCInst &Inst, unsigned N) const {
1496 assert(N == 1 && "Invalid number of operands!");
1497 int32_t Imm = Memory.OffsetImm->getValue();
1498 // FIXME: Handle #-0
1499 if (Imm == INT32_MIN) Imm = 0;
1500 Inst.addOperand(MCOperand::CreateImm(Imm));
1501 }
1502
Jim Grosbacha95ec992011-10-11 17:29:55 +00001503 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1504 assert(N == 2 && "Invalid number of operands!");
1505 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1506 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1507 }
1508
Jim Grosbachd3595712011-08-03 23:50:40 +00001509 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1510 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001511 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1512 if (!Memory.OffsetRegNum) {
Jim Grosbachd3595712011-08-03 23:50:40 +00001513 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1514 // Special case for #-0
1515 if (Val == INT32_MIN) Val = 0;
1516 if (Val < 0) Val = -Val;
1517 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1518 } else {
1519 // For register offset, we encode the shift type and negation flag
1520 // here.
Jim Grosbach871dff72011-10-11 15:59:20 +00001521 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1522 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001523 }
Jim Grosbach871dff72011-10-11 15:59:20 +00001524 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1525 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001526 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001527 }
1528
Jim Grosbachcd17c122011-08-04 23:01:30 +00001529 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1530 assert(N == 2 && "Invalid number of operands!");
1531 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1532 assert(CE && "non-constant AM2OffsetImm operand!");
1533 int32_t Val = CE->getValue();
1534 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1535 // Special case for #-0
1536 if (Val == INT32_MIN) Val = 0;
1537 if (Val < 0) Val = -Val;
1538 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1539 Inst.addOperand(MCOperand::CreateReg(0));
1540 Inst.addOperand(MCOperand::CreateImm(Val));
1541 }
1542
Jim Grosbach5b96b802011-08-10 20:29:19 +00001543 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1544 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach8648c102011-12-19 23:06:24 +00001545 // If we have an immediate that's not a constant, treat it as a label
1546 // reference needing a fixup. If it is a constant, it's something else
1547 // and we reject it.
1548 if (isImm()) {
1549 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1550 Inst.addOperand(MCOperand::CreateReg(0));
1551 Inst.addOperand(MCOperand::CreateImm(0));
1552 return;
1553 }
1554
Jim Grosbach871dff72011-10-11 15:59:20 +00001555 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1556 if (!Memory.OffsetRegNum) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00001557 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1558 // Special case for #-0
1559 if (Val == INT32_MIN) Val = 0;
1560 if (Val < 0) Val = -Val;
1561 Val = ARM_AM::getAM3Opc(AddSub, Val);
1562 } else {
1563 // For register offset, we encode the shift type and negation flag
1564 // here.
Jim Grosbach871dff72011-10-11 15:59:20 +00001565 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach5b96b802011-08-10 20:29:19 +00001566 }
Jim Grosbach871dff72011-10-11 15:59:20 +00001567 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1568 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach5b96b802011-08-10 20:29:19 +00001569 Inst.addOperand(MCOperand::CreateImm(Val));
1570 }
1571
1572 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1573 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001574 if (Kind == k_PostIndexRegister) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00001575 int32_t Val =
1576 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1577 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1578 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001579 return;
Jim Grosbach5b96b802011-08-10 20:29:19 +00001580 }
1581
1582 // Constant offset.
1583 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1584 int32_t Val = CE->getValue();
1585 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1586 // Special case for #-0
1587 if (Val == INT32_MIN) Val = 0;
1588 if (Val < 0) Val = -Val;
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001589 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach5b96b802011-08-10 20:29:19 +00001590 Inst.addOperand(MCOperand::CreateReg(0));
1591 Inst.addOperand(MCOperand::CreateImm(Val));
1592 }
1593
Jim Grosbachd3595712011-08-03 23:50:40 +00001594 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1595 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachfb2f1d62011-11-01 01:24:45 +00001596 // If we have an immediate that's not a constant, treat it as a label
1597 // reference needing a fixup. If it is a constant, it's something else
1598 // and we reject it.
1599 if (isImm()) {
1600 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1601 Inst.addOperand(MCOperand::CreateImm(0));
1602 return;
1603 }
1604
Jim Grosbachd3595712011-08-03 23:50:40 +00001605 // The lower two bits are always zero and as such are not encoded.
Jim Grosbach871dff72011-10-11 15:59:20 +00001606 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00001607 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1608 // Special case for #-0
1609 if (Val == INT32_MIN) Val = 0;
1610 if (Val < 0) Val = -Val;
1611 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbach871dff72011-10-11 15:59:20 +00001612 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001613 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00001614 }
1615
Jim Grosbach7db8d692011-09-08 22:07:06 +00001616 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1617 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach8648c102011-12-19 23:06:24 +00001618 // If we have an immediate that's not a constant, treat it as a label
1619 // reference needing a fixup. If it is a constant, it's something else
1620 // and we reject it.
1621 if (isImm()) {
1622 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1623 Inst.addOperand(MCOperand::CreateImm(0));
1624 return;
1625 }
1626
Jim Grosbach871dff72011-10-11 15:59:20 +00001627 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1628 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7db8d692011-09-08 22:07:06 +00001629 Inst.addOperand(MCOperand::CreateImm(Val));
1630 }
1631
Jim Grosbacha05627e2011-09-09 18:37:27 +00001632 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1633 assert(N == 2 && "Invalid number of operands!");
1634 // The lower two bits are always zero and as such are not encoded.
Jim Grosbach871dff72011-10-11 15:59:20 +00001635 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1636 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha05627e2011-09-09 18:37:27 +00001637 Inst.addOperand(MCOperand::CreateImm(Val));
1638 }
1639
Jim Grosbachd3595712011-08-03 23:50:40 +00001640 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1641 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001642 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1643 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001644 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner5d6f6a02010-10-29 00:27:31 +00001645 }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001646
Jim Grosbach2392c532011-09-07 23:39:14 +00001647 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1648 addMemImm8OffsetOperands(Inst, N);
1649 }
1650
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001651 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach2392c532011-09-07 23:39:14 +00001652 addMemImm8OffsetOperands(Inst, N);
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001653 }
1654
1655 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1656 assert(N == 2 && "Invalid number of operands!");
1657 // If this is an immediate, it's a label reference.
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001658 if (isImm()) {
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001659 addExpr(Inst, getImm());
1660 Inst.addOperand(MCOperand::CreateImm(0));
1661 return;
1662 }
1663
1664 // Otherwise, it's a normal memory reg+offset.
Jim Grosbach871dff72011-10-11 15:59:20 +00001665 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1666 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001667 Inst.addOperand(MCOperand::CreateImm(Val));
1668 }
1669
Jim Grosbachd3595712011-08-03 23:50:40 +00001670 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1671 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach95466ce2011-08-08 20:59:31 +00001672 // If this is an immediate, it's a label reference.
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001673 if (isImm()) {
Jim Grosbach95466ce2011-08-08 20:59:31 +00001674 addExpr(Inst, getImm());
1675 Inst.addOperand(MCOperand::CreateImm(0));
1676 return;
1677 }
1678
1679 // Otherwise, it's a normal memory reg+offset.
Jim Grosbach871dff72011-10-11 15:59:20 +00001680 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1681 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001682 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendling092a7bd2010-12-14 03:36:38 +00001683 }
Bill Wendling811c9362010-11-30 07:44:32 +00001684
Jim Grosbach05541f42011-09-19 22:21:13 +00001685 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1686 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001687 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1688 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach05541f42011-09-19 22:21:13 +00001689 }
1690
1691 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1692 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001693 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1694 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach05541f42011-09-19 22:21:13 +00001695 }
1696
Jim Grosbachd3595712011-08-03 23:50:40 +00001697 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1698 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001699 unsigned Val =
1700 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1701 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbach871dff72011-10-11 15:59:20 +00001702 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1703 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001704 Inst.addOperand(MCOperand::CreateImm(Val));
1705 }
1706
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001707 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1708 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001709 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1710 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1711 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001712 }
1713
Jim Grosbachd3595712011-08-03 23:50:40 +00001714 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1715 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001716 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1717 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001718 }
1719
Jim Grosbach3fe94e32011-08-19 17:55:24 +00001720 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1721 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001722 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1723 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach3fe94e32011-08-19 17:55:24 +00001724 Inst.addOperand(MCOperand::CreateImm(Val));
1725 }
1726
Jim Grosbach26d35872011-08-19 18:55:51 +00001727 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1728 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001729 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1730 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach26d35872011-08-19 18:55:51 +00001731 Inst.addOperand(MCOperand::CreateImm(Val));
1732 }
1733
Jim Grosbacha32c7532011-08-19 18:49:59 +00001734 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1735 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001736 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1737 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha32c7532011-08-19 18:49:59 +00001738 Inst.addOperand(MCOperand::CreateImm(Val));
1739 }
1740
Jim Grosbach23983d62011-08-19 18:13:48 +00001741 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1742 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001743 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1744 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach23983d62011-08-19 18:13:48 +00001745 Inst.addOperand(MCOperand::CreateImm(Val));
1746 }
1747
Jim Grosbachd3595712011-08-03 23:50:40 +00001748 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1749 assert(N == 1 && "Invalid number of operands!");
1750 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1751 assert(CE && "non-constant post-idx-imm8 operand!");
1752 int Imm = CE->getValue();
1753 bool isAdd = Imm >= 0;
Owen Andersonf02d98d2011-08-29 17:17:09 +00001754 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00001755 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1756 Inst.addOperand(MCOperand::CreateImm(Imm));
1757 }
1758
Jim Grosbach93981412011-10-11 21:55:36 +00001759 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1760 assert(N == 1 && "Invalid number of operands!");
1761 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1762 assert(CE && "non-constant post-idx-imm8s4 operand!");
1763 int Imm = CE->getValue();
1764 bool isAdd = Imm >= 0;
1765 if (Imm == INT32_MIN) Imm = 0;
1766 // Immediate is scaled by 4.
1767 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1768 Inst.addOperand(MCOperand::CreateImm(Imm));
1769 }
1770
Jim Grosbachd3595712011-08-03 23:50:40 +00001771 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1772 assert(N == 2 && "Invalid number of operands!");
1773 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachc320c852011-08-05 21:28:30 +00001774 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1775 }
1776
1777 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1778 assert(N == 2 && "Invalid number of operands!");
1779 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1780 // The sign, shift type, and shift amount are encoded in a single operand
1781 // using the AM2 encoding helpers.
1782 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1783 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1784 PostIdxReg.ShiftTy);
1785 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendling811c9362010-11-30 07:44:32 +00001786 }
1787
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001788 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1789 assert(N == 1 && "Invalid number of operands!");
1790 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1791 }
1792
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001793 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1794 assert(N == 1 && "Invalid number of operands!");
1795 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1796 }
1797
Jim Grosbach182b6a02011-11-29 23:51:09 +00001798 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001799 assert(N == 1 && "Invalid number of operands!");
1800 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1801 }
1802
Jim Grosbach04945c42011-12-02 00:35:16 +00001803 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1804 assert(N == 2 && "Invalid number of operands!");
1805 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1806 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1807 }
1808
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001809 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1810 assert(N == 1 && "Invalid number of operands!");
1811 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1812 }
1813
1814 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1815 assert(N == 1 && "Invalid number of operands!");
1816 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1817 }
1818
1819 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1820 assert(N == 1 && "Invalid number of operands!");
1821 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1822 }
1823
Jim Grosbach741cd732011-10-17 22:26:03 +00001824 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1825 assert(N == 1 && "Invalid number of operands!");
1826 // The immediate encodes the type of constant as well as the value.
1827 // Mask in that this is an i8 splat.
1828 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1829 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1830 }
1831
Jim Grosbachcda32ae2011-10-17 23:09:09 +00001832 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1833 assert(N == 1 && "Invalid number of operands!");
1834 // The immediate encodes the type of constant as well as the value.
1835 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1836 unsigned Value = CE->getValue();
1837 if (Value >= 256)
1838 Value = (Value >> 8) | 0xa00;
1839 else
1840 Value |= 0x800;
1841 Inst.addOperand(MCOperand::CreateImm(Value));
1842 }
1843
Jim Grosbach8211c052011-10-18 00:22:00 +00001844 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1845 assert(N == 1 && "Invalid number of operands!");
1846 // The immediate encodes the type of constant as well as the value.
1847 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1848 unsigned Value = CE->getValue();
1849 if (Value >= 256 && Value <= 0xff00)
1850 Value = (Value >> 8) | 0x200;
1851 else if (Value > 0xffff && Value <= 0xff0000)
1852 Value = (Value >> 16) | 0x400;
1853 else if (Value > 0xffffff)
1854 Value = (Value >> 24) | 0x600;
1855 Inst.addOperand(MCOperand::CreateImm(Value));
1856 }
1857
1858 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1859 assert(N == 1 && "Invalid number of operands!");
1860 // The immediate encodes the type of constant as well as the value.
1861 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1862 unsigned Value = CE->getValue();
1863 if (Value >= 256 && Value <= 0xffff)
1864 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1865 else if (Value > 0xffff && Value <= 0xffffff)
1866 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1867 else if (Value > 0xffffff)
1868 Value = (Value >> 24) | 0x600;
1869 Inst.addOperand(MCOperand::CreateImm(Value));
1870 }
1871
Jim Grosbach045b6c72011-12-19 23:51:07 +00001872 void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const {
1873 assert(N == 1 && "Invalid number of operands!");
1874 // The immediate encodes the type of constant as well as the value.
1875 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1876 unsigned Value = ~CE->getValue();
1877 if (Value >= 256 && Value <= 0xffff)
1878 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1879 else if (Value > 0xffff && Value <= 0xffffff)
1880 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1881 else if (Value > 0xffffff)
1882 Value = (Value >> 24) | 0x600;
1883 Inst.addOperand(MCOperand::CreateImm(Value));
1884 }
1885
Jim Grosbache4454e02011-10-18 16:18:11 +00001886 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1887 assert(N == 1 && "Invalid number of operands!");
1888 // The immediate encodes the type of constant as well as the value.
1889 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1890 uint64_t Value = CE->getValue();
1891 unsigned Imm = 0;
1892 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1893 Imm |= (Value & 1) << i;
1894 }
1895 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1896 }
1897
Jim Grosbach602aa902011-07-13 15:34:57 +00001898 virtual void print(raw_ostream &OS) const;
Daniel Dunbarebace222010-08-11 06:37:04 +00001899
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001900 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001901 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001902 Op->ITMask.Mask = Mask;
1903 Op->StartLoc = S;
1904 Op->EndLoc = S;
1905 return Op;
1906 }
1907
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001908 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001909 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001910 Op->CC.Val = CC;
1911 Op->StartLoc = S;
1912 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001913 return Op;
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001914 }
1915
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001916 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001917 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001918 Op->Cop.Val = CopVal;
1919 Op->StartLoc = S;
1920 Op->EndLoc = S;
1921 return Op;
1922 }
1923
1924 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001925 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001926 Op->Cop.Val = CopVal;
1927 Op->StartLoc = S;
1928 Op->EndLoc = S;
1929 return Op;
1930 }
1931
Jim Grosbach48399582011-10-12 17:34:41 +00001932 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1933 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1934 Op->Cop.Val = Val;
1935 Op->StartLoc = S;
1936 Op->EndLoc = E;
1937 return Op;
1938 }
1939
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001940 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001941 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001942 Op->Reg.RegNum = RegNum;
1943 Op->StartLoc = S;
1944 Op->EndLoc = S;
1945 return Op;
1946 }
1947
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001948 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001949 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001950 Op->Tok.Data = Str.data();
1951 Op->Tok.Length = Str.size();
1952 Op->StartLoc = S;
1953 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001954 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001955 }
1956
Bill Wendling2063b842010-11-18 23:43:05 +00001957 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001958 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001959 Op->Reg.RegNum = RegNum;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001960 Op->StartLoc = S;
1961 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001962 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001963 }
1964
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001965 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1966 unsigned SrcReg,
1967 unsigned ShiftReg,
1968 unsigned ShiftImm,
1969 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001970 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachac798e12011-07-25 20:49:51 +00001971 Op->RegShiftedReg.ShiftTy = ShTy;
1972 Op->RegShiftedReg.SrcReg = SrcReg;
1973 Op->RegShiftedReg.ShiftReg = ShiftReg;
1974 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001975 Op->StartLoc = S;
1976 Op->EndLoc = E;
1977 return Op;
1978 }
1979
Owen Andersonb595ed02011-07-21 18:54:16 +00001980 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1981 unsigned SrcReg,
1982 unsigned ShiftImm,
1983 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001984 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachac798e12011-07-25 20:49:51 +00001985 Op->RegShiftedImm.ShiftTy = ShTy;
1986 Op->RegShiftedImm.SrcReg = SrcReg;
1987 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Andersonb595ed02011-07-21 18:54:16 +00001988 Op->StartLoc = S;
1989 Op->EndLoc = E;
1990 return Op;
1991 }
1992
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001993 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001994 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001995 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001996 Op->ShifterImm.isASR = isASR;
1997 Op->ShifterImm.Imm = Imm;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001998 Op->StartLoc = S;
1999 Op->EndLoc = E;
2000 return Op;
2001 }
2002
Jim Grosbach833b9d32011-07-27 20:15:40 +00002003 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002004 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach833b9d32011-07-27 20:15:40 +00002005 Op->RotImm.Imm = Imm;
2006 Op->StartLoc = S;
2007 Op->EndLoc = E;
2008 return Op;
2009 }
2010
Jim Grosbach864b6092011-07-28 21:34:26 +00002011 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
2012 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002013 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach864b6092011-07-28 21:34:26 +00002014 Op->Bitfield.LSB = LSB;
2015 Op->Bitfield.Width = Width;
2016 Op->StartLoc = S;
2017 Op->EndLoc = E;
2018 return Op;
2019 }
2020
Bill Wendling2cae3272010-11-09 22:44:22 +00002021 static ARMOperand *
Bill Wendlingbed94652010-11-09 23:28:44 +00002022 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00002023 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002024 KindTy Kind = k_RegisterList;
Bill Wendling9898ac92010-11-17 04:32:08 +00002025
Jim Grosbach75461af2011-09-13 22:56:44 +00002026 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002027 Kind = k_DPRRegisterList;
Jim Grosbach75461af2011-09-13 22:56:44 +00002028 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng9eec7642011-07-25 21:32:49 +00002029 contains(Regs.front().first))
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002030 Kind = k_SPRRegisterList;
Bill Wendling9898ac92010-11-17 04:32:08 +00002031
2032 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendlingbed94652010-11-09 23:28:44 +00002033 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00002034 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling0ab0f672010-11-18 21:50:54 +00002035 Op->Registers.push_back(I->first);
Bill Wendling20b5ea982010-11-19 00:38:19 +00002036 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00002037 Op->StartLoc = StartLoc;
2038 Op->EndLoc = EndLoc;
Bill Wendling7cef4472010-11-06 19:56:04 +00002039 return Op;
2040 }
2041
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002042 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
Jim Grosbach2f50e922011-12-15 21:44:33 +00002043 bool isDoubleSpaced, SMLoc S, SMLoc E) {
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002044 ARMOperand *Op = new ARMOperand(k_VectorList);
2045 Op->VectorList.RegNum = RegNum;
2046 Op->VectorList.Count = Count;
Jim Grosbach2f50e922011-12-15 21:44:33 +00002047 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002048 Op->StartLoc = S;
2049 Op->EndLoc = E;
2050 return Op;
2051 }
2052
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002053 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
Jim Grosbachc5af54e2011-12-21 00:38:54 +00002054 bool isDoubleSpaced,
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002055 SMLoc S, SMLoc E) {
2056 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
2057 Op->VectorList.RegNum = RegNum;
2058 Op->VectorList.Count = Count;
Jim Grosbachc5af54e2011-12-21 00:38:54 +00002059 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002060 Op->StartLoc = S;
2061 Op->EndLoc = E;
2062 return Op;
2063 }
2064
Jim Grosbach04945c42011-12-02 00:35:16 +00002065 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
Jim Grosbach75e2ab52011-12-20 19:21:26 +00002066 unsigned Index,
2067 bool isDoubleSpaced,
2068 SMLoc S, SMLoc E) {
Jim Grosbach04945c42011-12-02 00:35:16 +00002069 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
2070 Op->VectorList.RegNum = RegNum;
2071 Op->VectorList.Count = Count;
2072 Op->VectorList.LaneIndex = Index;
Jim Grosbach75e2ab52011-12-20 19:21:26 +00002073 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach04945c42011-12-02 00:35:16 +00002074 Op->StartLoc = S;
2075 Op->EndLoc = E;
2076 return Op;
2077 }
2078
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002079 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
2080 MCContext &Ctx) {
2081 ARMOperand *Op = new ARMOperand(k_VectorIndex);
2082 Op->VectorIndex.Val = Idx;
2083 Op->StartLoc = S;
2084 Op->EndLoc = E;
2085 return Op;
2086 }
2087
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002088 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002089 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002090 Op->Imm.Val = Val;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002091 Op->StartLoc = S;
2092 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002093 return Op;
Kevin Enderbyf5079942009-10-13 22:19:02 +00002094 }
2095
Jim Grosbachd3595712011-08-03 23:50:40 +00002096 static ARMOperand *CreateMem(unsigned BaseRegNum,
2097 const MCConstantExpr *OffsetImm,
2098 unsigned OffsetRegNum,
2099 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00002100 unsigned ShiftImm,
Jim Grosbacha95ec992011-10-11 17:29:55 +00002101 unsigned Alignment,
Jim Grosbachd3595712011-08-03 23:50:40 +00002102 bool isNegative,
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002103 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002104 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbach871dff72011-10-11 15:59:20 +00002105 Op->Memory.BaseRegNum = BaseRegNum;
2106 Op->Memory.OffsetImm = OffsetImm;
2107 Op->Memory.OffsetRegNum = OffsetRegNum;
2108 Op->Memory.ShiftType = ShiftType;
2109 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbacha95ec992011-10-11 17:29:55 +00002110 Op->Memory.Alignment = Alignment;
Jim Grosbach871dff72011-10-11 15:59:20 +00002111 Op->Memory.isNegative = isNegative;
Jim Grosbachd3595712011-08-03 23:50:40 +00002112 Op->StartLoc = S;
2113 Op->EndLoc = E;
2114 return Op;
2115 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00002116
Jim Grosbachc320c852011-08-05 21:28:30 +00002117 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
2118 ARM_AM::ShiftOpc ShiftTy,
2119 unsigned ShiftImm,
Jim Grosbachd3595712011-08-03 23:50:40 +00002120 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002121 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbachd3595712011-08-03 23:50:40 +00002122 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachc320c852011-08-05 21:28:30 +00002123 Op->PostIdxReg.isAdd = isAdd;
2124 Op->PostIdxReg.ShiftTy = ShiftTy;
2125 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002126 Op->StartLoc = S;
2127 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002128 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002129 }
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002130
2131 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002132 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002133 Op->MBOpt.Val = Opt;
2134 Op->StartLoc = S;
2135 Op->EndLoc = S;
2136 return Op;
2137 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002138
2139 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002140 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002141 Op->IFlags.Val = IFlags;
2142 Op->StartLoc = S;
2143 Op->EndLoc = S;
2144 return Op;
2145 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002146
2147 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002148 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002149 Op->MMask.Val = MMask;
2150 Op->StartLoc = S;
2151 Op->EndLoc = S;
2152 return Op;
2153 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002154};
2155
2156} // end anonymous namespace.
2157
Jim Grosbach602aa902011-07-13 15:34:57 +00002158void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002159 switch (Kind) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002160 case k_CondCode:
Daniel Dunbar2be732a2011-01-10 15:26:21 +00002161 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002162 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002163 case k_CCOut:
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00002164 OS << "<ccout " << getReg() << ">";
2165 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002166 case k_ITCondMask: {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00002167 static const char *MaskStr[] = {
2168 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2169 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2170 };
Jim Grosbach3d1eac82011-08-26 21:43:41 +00002171 assert((ITMask.Mask & 0xf) == ITMask.Mask);
2172 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2173 break;
2174 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002175 case k_CoprocNum:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002176 OS << "<coprocessor number: " << getCoproc() << ">";
2177 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002178 case k_CoprocReg:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002179 OS << "<coprocessor register: " << getCoproc() << ">";
2180 break;
Jim Grosbach48399582011-10-12 17:34:41 +00002181 case k_CoprocOption:
2182 OS << "<coprocessor option: " << CoprocOption.Val << ">";
2183 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002184 case k_MSRMask:
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002185 OS << "<mask: " << getMSRMask() << ">";
2186 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002187 case k_Immediate:
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002188 getImm()->print(OS);
2189 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002190 case k_MemBarrierOpt:
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002191 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2192 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002193 case k_Memory:
Daniel Dunbarbcd8eb02011-01-18 05:55:21 +00002194 OS << "<memory "
Jim Grosbach871dff72011-10-11 15:59:20 +00002195 << " base:" << Memory.BaseRegNum;
Daniel Dunbarbcd8eb02011-01-18 05:55:21 +00002196 OS << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002197 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002198 case k_PostIndexRegister:
Jim Grosbachc320c852011-08-05 21:28:30 +00002199 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2200 << PostIdxReg.RegNum;
2201 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2202 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2203 << PostIdxReg.ShiftImm;
2204 OS << ">";
Jim Grosbachd3595712011-08-03 23:50:40 +00002205 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002206 case k_ProcIFlags: {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002207 OS << "<ARM_PROC::";
2208 unsigned IFlags = getProcIFlags();
2209 for (int i=2; i >= 0; --i)
2210 if (IFlags & (1 << i))
2211 OS << ARM_PROC::IFlagsToString(1 << i);
2212 OS << ">";
2213 break;
2214 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002215 case k_Register:
Bill Wendling2063b842010-11-18 23:43:05 +00002216 OS << "<register " << getReg() << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002217 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002218 case k_ShifterImmediate:
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002219 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2220 << " #" << ShifterImm.Imm << ">";
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002221 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002222 case k_ShiftedRegister:
Owen Andersonb595ed02011-07-21 18:54:16 +00002223 OS << "<so_reg_reg "
Jim Grosbach01e04392011-11-16 21:46:50 +00002224 << RegShiftedReg.SrcReg << " "
2225 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2226 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002227 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002228 case k_ShiftedImmediate:
Owen Andersonb595ed02011-07-21 18:54:16 +00002229 OS << "<so_reg_imm "
Jim Grosbach01e04392011-11-16 21:46:50 +00002230 << RegShiftedImm.SrcReg << " "
2231 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2232 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Andersonb595ed02011-07-21 18:54:16 +00002233 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002234 case k_RotateImmediate:
Jim Grosbach833b9d32011-07-27 20:15:40 +00002235 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2236 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002237 case k_BitfieldDescriptor:
Jim Grosbach864b6092011-07-28 21:34:26 +00002238 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2239 << ", width: " << Bitfield.Width << ">";
2240 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002241 case k_RegisterList:
2242 case k_DPRRegisterList:
2243 case k_SPRRegisterList: {
Bill Wendling7cef4472010-11-06 19:56:04 +00002244 OS << "<register_list ";
Bill Wendling7cef4472010-11-06 19:56:04 +00002245
Bill Wendlingbed94652010-11-09 23:28:44 +00002246 const SmallVectorImpl<unsigned> &RegList = getRegList();
2247 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00002248 I = RegList.begin(), E = RegList.end(); I != E; ) {
2249 OS << *I;
2250 if (++I < E) OS << ", ";
Bill Wendling7cef4472010-11-06 19:56:04 +00002251 }
2252
2253 OS << ">";
2254 break;
2255 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002256 case k_VectorList:
2257 OS << "<vector_list " << VectorList.Count << " * "
2258 << VectorList.RegNum << ">";
2259 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002260 case k_VectorListAllLanes:
2261 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2262 << VectorList.RegNum << ">";
2263 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00002264 case k_VectorListIndexed:
2265 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2266 << VectorList.Count << " * " << VectorList.RegNum << ">";
2267 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002268 case k_Token:
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002269 OS << "'" << getToken() << "'";
2270 break;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002271 case k_VectorIndex:
2272 OS << "<vectorindex " << getVectorIndex() << ">";
2273 break;
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002274 }
2275}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00002276
2277/// @name Auto-generated Match Functions
2278/// {
2279
2280static unsigned MatchRegisterName(StringRef Name);
2281
2282/// }
2283
Bob Wilsonfb0bd042011-02-03 21:46:10 +00002284bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2285 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbachab5830e2011-12-14 02:16:11 +00002286 StartLoc = Parser.getTok().getLoc();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002287 RegNo = tryParseRegister();
Jim Grosbachab5830e2011-12-14 02:16:11 +00002288 EndLoc = Parser.getTok().getLoc();
Roman Divacky36b1b472011-01-27 17:14:22 +00002289
2290 return (RegNo == (unsigned)-1);
2291}
2292
Kevin Enderby8be42bd2009-10-30 22:55:57 +00002293/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattner44e5981c2010-10-30 04:09:10 +00002294/// and if it is a register name the token is eaten and the register number is
2295/// returned. Otherwise return -1.
2296///
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002297int ARMAsmParser::tryParseRegister() {
Chris Lattner44e5981c2010-10-30 04:09:10 +00002298 const AsmToken &Tok = Parser.getTok();
Jim Grosbachd3595712011-08-03 23:50:40 +00002299 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbach99710a82010-11-01 16:44:21 +00002300
Benjamin Kramer20baffb2011-11-06 20:37:06 +00002301 std::string lowerCase = Tok.getString().lower();
Owen Andersona098d152011-01-13 22:50:36 +00002302 unsigned RegNum = MatchRegisterName(lowerCase);
2303 if (!RegNum) {
2304 RegNum = StringSwitch<unsigned>(lowerCase)
2305 .Case("r13", ARM::SP)
2306 .Case("r14", ARM::LR)
2307 .Case("r15", ARM::PC)
2308 .Case("ip", ARM::R12)
Jim Grosbach4edc7362011-12-08 19:27:38 +00002309 // Additional register name aliases for 'gas' compatibility.
2310 .Case("a1", ARM::R0)
2311 .Case("a2", ARM::R1)
2312 .Case("a3", ARM::R2)
2313 .Case("a4", ARM::R3)
2314 .Case("v1", ARM::R4)
2315 .Case("v2", ARM::R5)
2316 .Case("v3", ARM::R6)
2317 .Case("v4", ARM::R7)
2318 .Case("v5", ARM::R8)
2319 .Case("v6", ARM::R9)
2320 .Case("v7", ARM::R10)
2321 .Case("v8", ARM::R11)
2322 .Case("sb", ARM::R9)
2323 .Case("sl", ARM::R10)
2324 .Case("fp", ARM::R11)
Owen Andersona098d152011-01-13 22:50:36 +00002325 .Default(0);
2326 }
Jim Grosbachab5830e2011-12-14 02:16:11 +00002327 if (!RegNum) {
Jim Grosbachcd22e4a2011-12-20 23:11:00 +00002328 // Check for aliases registered via .req. Canonicalize to lower case.
2329 // That's more consistent since register names are case insensitive, and
2330 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2331 StringMap<unsigned>::const_iterator Entry = RegisterReqs.find(lowerCase);
Jim Grosbachab5830e2011-12-14 02:16:11 +00002332 // If no match, return failure.
2333 if (Entry == RegisterReqs.end())
2334 return -1;
2335 Parser.Lex(); // Eat identifier token.
2336 return Entry->getValue();
2337 }
Bob Wilsonfb0bd042011-02-03 21:46:10 +00002338
Chris Lattner44e5981c2010-10-30 04:09:10 +00002339 Parser.Lex(); // Eat identifier token.
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002340
Chris Lattner44e5981c2010-10-30 04:09:10 +00002341 return RegNum;
2342}
Jim Grosbach99710a82010-11-01 16:44:21 +00002343
Jim Grosbachbb24c592011-07-13 18:49:30 +00002344// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2345// If a recoverable error occurs, return 1. If an irrecoverable error
2346// occurs, return -1. An irrecoverable error is one where tokens have been
2347// consumed in the process of trying to parse the shifter (i.e., when it is
2348// indeed a shifter operand, but malformed).
Jim Grosbach0d6022d2011-07-26 20:41:24 +00002349int ARMAsmParser::tryParseShiftRegister(
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002350 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2351 SMLoc S = Parser.getTok().getLoc();
2352 const AsmToken &Tok = Parser.getTok();
2353 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2354
Benjamin Kramer20baffb2011-11-06 20:37:06 +00002355 std::string lowerCase = Tok.getString().lower();
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002356 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbach3b559ff2011-12-07 23:40:58 +00002357 .Case("asl", ARM_AM::lsl)
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002358 .Case("lsl", ARM_AM::lsl)
2359 .Case("lsr", ARM_AM::lsr)
2360 .Case("asr", ARM_AM::asr)
2361 .Case("ror", ARM_AM::ror)
2362 .Case("rrx", ARM_AM::rrx)
2363 .Default(ARM_AM::no_shift);
2364
2365 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbachbb24c592011-07-13 18:49:30 +00002366 return 1;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002367
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002368 Parser.Lex(); // Eat the operator.
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002369
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002370 // The source register for the shift has already been added to the
2371 // operand list, so we need to pop it off and combine it into the shifted
2372 // register operand instead.
Benjamin Kramer1757e7a2011-07-14 18:41:22 +00002373 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002374 if (!PrevOp->isReg())
2375 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2376 int SrcReg = PrevOp->getReg();
2377 int64_t Imm = 0;
2378 int ShiftReg = 0;
2379 if (ShiftTy == ARM_AM::rrx) {
2380 // RRX Doesn't have an explicit shift amount. The encoder expects
2381 // the shift register to be the same as the source register. Seems odd,
2382 // but OK.
2383 ShiftReg = SrcReg;
2384 } else {
2385 // Figure out if this is shifted by a constant or a register (for non-RRX).
Jim Grosbachef70e9b2011-12-09 22:25:03 +00002386 if (Parser.getTok().is(AsmToken::Hash) ||
2387 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002388 Parser.Lex(); // Eat hash.
2389 SMLoc ImmLoc = Parser.getTok().getLoc();
2390 const MCExpr *ShiftExpr = 0;
Jim Grosbachbb24c592011-07-13 18:49:30 +00002391 if (getParser().ParseExpression(ShiftExpr)) {
2392 Error(ImmLoc, "invalid immediate shift value");
2393 return -1;
2394 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002395 // The expression must be evaluatable as an immediate.
2396 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbachbb24c592011-07-13 18:49:30 +00002397 if (!CE) {
2398 Error(ImmLoc, "invalid immediate shift value");
2399 return -1;
2400 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002401 // Range check the immediate.
2402 // lsl, ror: 0 <= imm <= 31
2403 // lsr, asr: 0 <= imm <= 32
2404 Imm = CE->getValue();
2405 if (Imm < 0 ||
2406 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2407 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbachbb24c592011-07-13 18:49:30 +00002408 Error(ImmLoc, "immediate shift value out of range");
2409 return -1;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002410 }
Jim Grosbach21488b82011-12-22 17:37:00 +00002411 // shift by zero is a nop. Always send it through as lsl.
2412 // ('as' compatibility)
2413 if (Imm == 0)
2414 ShiftTy = ARM_AM::lsl;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002415 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002416 ShiftReg = tryParseRegister();
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002417 SMLoc L = Parser.getTok().getLoc();
Jim Grosbachbb24c592011-07-13 18:49:30 +00002418 if (ShiftReg == -1) {
2419 Error (L, "expected immediate or register in shift operand");
2420 return -1;
2421 }
2422 } else {
2423 Error (Parser.getTok().getLoc(),
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002424 "expected immediate or register in shift operand");
Jim Grosbachbb24c592011-07-13 18:49:30 +00002425 return -1;
2426 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002427 }
2428
Owen Andersonb595ed02011-07-21 18:54:16 +00002429 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2430 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachac798e12011-07-25 20:49:51 +00002431 ShiftReg, Imm,
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002432 S, Parser.getTok().getLoc()));
Owen Andersonb595ed02011-07-21 18:54:16 +00002433 else
2434 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2435 S, Parser.getTok().getLoc()));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002436
Jim Grosbachbb24c592011-07-13 18:49:30 +00002437 return 0;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002438}
2439
2440
Bill Wendling2063b842010-11-18 23:43:05 +00002441/// Try to parse a register name. The token must be an Identifier when called.
2442/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2443/// if there is a "writeback". 'true' if it's not a register.
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002444///
Kevin Enderby8be42bd2009-10-30 22:55:57 +00002445/// TODO this is likely to change to allow different register types and or to
2446/// parse for a specific register type.
Bill Wendling2063b842010-11-18 23:43:05 +00002447bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002448tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattner44e5981c2010-10-30 04:09:10 +00002449 SMLoc S = Parser.getTok().getLoc();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002450 int RegNo = tryParseRegister();
Bill Wendlinge18980a2010-11-06 22:36:58 +00002451 if (RegNo == -1)
Bill Wendling2063b842010-11-18 23:43:05 +00002452 return true;
Jim Grosbach99710a82010-11-01 16:44:21 +00002453
Bill Wendling2063b842010-11-18 23:43:05 +00002454 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002455
Chris Lattner44e5981c2010-10-30 04:09:10 +00002456 const AsmToken &ExclaimTok = Parser.getTok();
2457 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling2063b842010-11-18 23:43:05 +00002458 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2459 ExclaimTok.getLoc()));
Chris Lattner44e5981c2010-10-30 04:09:10 +00002460 Parser.Lex(); // Eat exclaim token
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002461 return false;
2462 }
2463
2464 // Also check for an index operand. This is only legal for vector registers,
2465 // but that'll get caught OK in operand matching, so we don't need to
2466 // explicitly filter everything else out here.
2467 if (Parser.getTok().is(AsmToken::LBrac)) {
2468 SMLoc SIdx = Parser.getTok().getLoc();
2469 Parser.Lex(); // Eat left bracket token.
2470
2471 const MCExpr *ImmVal;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002472 if (getParser().ParseExpression(ImmVal))
2473 return MatchOperand_ParseFail;
2474 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2475 if (!MCE) {
2476 TokError("immediate value expected for vector index");
2477 return MatchOperand_ParseFail;
2478 }
2479
2480 SMLoc E = Parser.getTok().getLoc();
2481 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2482 Error(E, "']' expected");
2483 return MatchOperand_ParseFail;
2484 }
2485
2486 Parser.Lex(); // Eat right bracket token.
2487
2488 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2489 SIdx, E,
2490 getContext()));
Kevin Enderby2207e5f2009-10-07 18:01:35 +00002491 }
2492
Bill Wendling2063b842010-11-18 23:43:05 +00002493 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002494}
2495
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002496/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2497/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2498/// "c5", ...
2499static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002500 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2501 // but efficient.
2502 switch (Name.size()) {
David Blaikie46a9f012012-01-20 21:51:11 +00002503 default: return -1;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002504 case 2:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002505 if (Name[0] != CoprocOp)
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002506 return -1;
2507 switch (Name[1]) {
2508 default: return -1;
2509 case '0': return 0;
2510 case '1': return 1;
2511 case '2': return 2;
2512 case '3': return 3;
2513 case '4': return 4;
2514 case '5': return 5;
2515 case '6': return 6;
2516 case '7': return 7;
2517 case '8': return 8;
2518 case '9': return 9;
2519 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002520 case 3:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002521 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002522 return -1;
2523 switch (Name[2]) {
2524 default: return -1;
2525 case '0': return 10;
2526 case '1': return 11;
2527 case '2': return 12;
2528 case '3': return 13;
2529 case '4': return 14;
2530 case '5': return 15;
2531 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002532 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002533}
2534
Jim Grosbach3d1eac82011-08-26 21:43:41 +00002535/// parseITCondCode - Try to parse a condition code for an IT instruction.
2536ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2537parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2538 SMLoc S = Parser.getTok().getLoc();
2539 const AsmToken &Tok = Parser.getTok();
2540 if (!Tok.is(AsmToken::Identifier))
2541 return MatchOperand_NoMatch;
2542 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2543 .Case("eq", ARMCC::EQ)
2544 .Case("ne", ARMCC::NE)
2545 .Case("hs", ARMCC::HS)
2546 .Case("cs", ARMCC::HS)
2547 .Case("lo", ARMCC::LO)
2548 .Case("cc", ARMCC::LO)
2549 .Case("mi", ARMCC::MI)
2550 .Case("pl", ARMCC::PL)
2551 .Case("vs", ARMCC::VS)
2552 .Case("vc", ARMCC::VC)
2553 .Case("hi", ARMCC::HI)
2554 .Case("ls", ARMCC::LS)
2555 .Case("ge", ARMCC::GE)
2556 .Case("lt", ARMCC::LT)
2557 .Case("gt", ARMCC::GT)
2558 .Case("le", ARMCC::LE)
2559 .Case("al", ARMCC::AL)
2560 .Default(~0U);
2561 if (CC == ~0U)
2562 return MatchOperand_NoMatch;
2563 Parser.Lex(); // Eat the token.
2564
2565 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2566
2567 return MatchOperand_Success;
2568}
2569
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002570/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002571/// token must be an Identifier when called, and if it is a coprocessor
2572/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002573ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002574parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002575 SMLoc S = Parser.getTok().getLoc();
2576 const AsmToken &Tok = Parser.getTok();
Jim Grosbach54a20ed2011-10-12 20:54:17 +00002577 if (Tok.isNot(AsmToken::Identifier))
2578 return MatchOperand_NoMatch;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002579
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002580 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002581 if (Num == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002582 return MatchOperand_NoMatch;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002583
2584 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002585 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002586 return MatchOperand_Success;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002587}
2588
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002589/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002590/// token must be an Identifier when called, and if it is a coprocessor
2591/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002592ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002593parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002594 SMLoc S = Parser.getTok().getLoc();
2595 const AsmToken &Tok = Parser.getTok();
Jim Grosbach54a20ed2011-10-12 20:54:17 +00002596 if (Tok.isNot(AsmToken::Identifier))
2597 return MatchOperand_NoMatch;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002598
2599 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2600 if (Reg == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002601 return MatchOperand_NoMatch;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002602
2603 Parser.Lex(); // Eat identifier token.
2604 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002605 return MatchOperand_Success;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002606}
2607
Jim Grosbach48399582011-10-12 17:34:41 +00002608/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2609/// coproc_option : '{' imm0_255 '}'
2610ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2611parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2612 SMLoc S = Parser.getTok().getLoc();
2613
2614 // If this isn't a '{', this isn't a coprocessor immediate operand.
2615 if (Parser.getTok().isNot(AsmToken::LCurly))
2616 return MatchOperand_NoMatch;
2617 Parser.Lex(); // Eat the '{'
2618
2619 const MCExpr *Expr;
2620 SMLoc Loc = Parser.getTok().getLoc();
2621 if (getParser().ParseExpression(Expr)) {
2622 Error(Loc, "illegal expression");
2623 return MatchOperand_ParseFail;
2624 }
2625 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2626 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2627 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2628 return MatchOperand_ParseFail;
2629 }
2630 int Val = CE->getValue();
2631
2632 // Check for and consume the closing '}'
2633 if (Parser.getTok().isNot(AsmToken::RCurly))
2634 return MatchOperand_ParseFail;
2635 SMLoc E = Parser.getTok().getLoc();
2636 Parser.Lex(); // Eat the '}'
2637
2638 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2639 return MatchOperand_Success;
2640}
2641
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002642// For register list parsing, we need to map from raw GPR register numbering
2643// to the enumeration values. The enumeration values aren't sorted by
2644// register number due to our using "sp", "lr" and "pc" as canonical names.
2645static unsigned getNextRegister(unsigned Reg) {
2646 // If this is a GPR, we need to do it manually, otherwise we can rely
2647 // on the sort ordering of the enumeration since the other reg-classes
2648 // are sane.
2649 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2650 return Reg + 1;
2651 switch(Reg) {
2652 default: assert(0 && "Invalid GPR number!");
2653 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2654 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2655 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2656 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2657 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2658 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2659 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2660 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2661 }
2662}
2663
Jim Grosbach85a23432011-11-11 21:27:40 +00002664// Return the low-subreg of a given Q register.
2665static unsigned getDRegFromQReg(unsigned QReg) {
2666 switch (QReg) {
2667 default: llvm_unreachable("expected a Q register!");
2668 case ARM::Q0: return ARM::D0;
2669 case ARM::Q1: return ARM::D2;
2670 case ARM::Q2: return ARM::D4;
2671 case ARM::Q3: return ARM::D6;
2672 case ARM::Q4: return ARM::D8;
2673 case ARM::Q5: return ARM::D10;
2674 case ARM::Q6: return ARM::D12;
2675 case ARM::Q7: return ARM::D14;
2676 case ARM::Q8: return ARM::D16;
Jim Grosbacha92a5d82011-11-15 21:01:30 +00002677 case ARM::Q9: return ARM::D18;
Jim Grosbach85a23432011-11-11 21:27:40 +00002678 case ARM::Q10: return ARM::D20;
2679 case ARM::Q11: return ARM::D22;
2680 case ARM::Q12: return ARM::D24;
2681 case ARM::Q13: return ARM::D26;
2682 case ARM::Q14: return ARM::D28;
2683 case ARM::Q15: return ARM::D30;
2684 }
2685}
2686
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002687/// Parse a register list.
Bill Wendling2063b842010-11-18 23:43:05 +00002688bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002689parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan936b0d32010-01-19 21:44:56 +00002690 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00002691 "Token is not a Left Curly Brace");
Bill Wendlinge18980a2010-11-06 22:36:58 +00002692 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002693 Parser.Lex(); // Eat '{' token.
2694 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbya2b99102009-10-09 21:12:28 +00002695
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002696 // Check the first register in the list to see what register class
2697 // this is a list of.
2698 int Reg = tryParseRegister();
2699 if (Reg == -1)
2700 return Error(RegLoc, "register expected");
2701
Jim Grosbach85a23432011-11-11 21:27:40 +00002702 // The reglist instructions have at most 16 registers, so reserve
2703 // space for that many.
2704 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2705
2706 // Allow Q regs and just interpret them as the two D sub-registers.
2707 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2708 Reg = getDRegFromQReg(Reg);
2709 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2710 ++Reg;
2711 }
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00002712 const MCRegisterClass *RC;
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002713 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2714 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2715 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2716 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2717 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2718 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2719 else
2720 return Error(RegLoc, "invalid register in register list");
2721
Jim Grosbach85a23432011-11-11 21:27:40 +00002722 // Store the register.
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002723 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbya2b99102009-10-09 21:12:28 +00002724
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002725 // This starts immediately after the first register token in the list,
2726 // so we can see either a comma or a minus (range separator) as a legal
2727 // next token.
2728 while (Parser.getTok().is(AsmToken::Comma) ||
2729 Parser.getTok().is(AsmToken::Minus)) {
2730 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache891fe82011-11-15 23:19:15 +00002731 Parser.Lex(); // Eat the minus.
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002732 SMLoc EndLoc = Parser.getTok().getLoc();
2733 int EndReg = tryParseRegister();
2734 if (EndReg == -1)
2735 return Error(EndLoc, "register expected");
Jim Grosbach85a23432011-11-11 21:27:40 +00002736 // Allow Q regs and just interpret them as the two D sub-registers.
2737 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2738 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002739 // If the register is the same as the start reg, there's nothing
2740 // more to do.
2741 if (Reg == EndReg)
2742 continue;
2743 // The register must be in the same register class as the first.
2744 if (!RC->contains(EndReg))
2745 return Error(EndLoc, "invalid register in register list");
2746 // Ranges must go from low to high.
2747 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2748 return Error(EndLoc, "bad range in register list");
Kevin Enderbya2b99102009-10-09 21:12:28 +00002749
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002750 // Add all the registers in the range to the register list.
2751 while (Reg != EndReg) {
2752 Reg = getNextRegister(Reg);
2753 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2754 }
2755 continue;
2756 }
2757 Parser.Lex(); // Eat the comma.
2758 RegLoc = Parser.getTok().getLoc();
2759 int OldReg = Reg;
Jim Grosbach98bc7972011-12-08 21:34:20 +00002760 const AsmToken RegTok = Parser.getTok();
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002761 Reg = tryParseRegister();
2762 if (Reg == -1)
Jim Grosbach3337e392011-09-12 23:36:42 +00002763 return Error(RegLoc, "register expected");
Jim Grosbach85a23432011-11-11 21:27:40 +00002764 // Allow Q regs and just interpret them as the two D sub-registers.
2765 bool isQReg = false;
2766 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2767 Reg = getDRegFromQReg(Reg);
2768 isQReg = true;
2769 }
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002770 // The register must be in the same register class as the first.
2771 if (!RC->contains(Reg))
2772 return Error(RegLoc, "invalid register in register list");
2773 // List must be monotonically increasing.
Jim Grosbach98bc7972011-12-08 21:34:20 +00002774 if (getARMRegisterNumbering(Reg) < getARMRegisterNumbering(OldReg))
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002775 return Error(RegLoc, "register list not in ascending order");
Jim Grosbach98bc7972011-12-08 21:34:20 +00002776 if (getARMRegisterNumbering(Reg) == getARMRegisterNumbering(OldReg)) {
2777 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
2778 ") in register list");
2779 continue;
2780 }
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002781 // VFP register lists must also be contiguous.
2782 // It's OK to use the enumeration values directly here rather, as the
2783 // VFP register classes have the enum sorted properly.
2784 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2785 Reg != OldReg + 1)
2786 return Error(RegLoc, "non-contiguous register range");
2787 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbach85a23432011-11-11 21:27:40 +00002788 if (isQReg)
2789 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge18980a2010-11-06 22:36:58 +00002790 }
2791
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002792 SMLoc E = Parser.getTok().getLoc();
2793 if (Parser.getTok().isNot(AsmToken::RCurly))
2794 return Error(E, "'}' expected");
2795 Parser.Lex(); // Eat '}' token.
2796
Jim Grosbach18bf3632011-12-13 21:48:29 +00002797 // Push the register list operand.
Bill Wendling2063b842010-11-18 23:43:05 +00002798 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
Jim Grosbach18bf3632011-12-13 21:48:29 +00002799
2800 // The ARM system instruction variants for LDM/STM have a '^' token here.
2801 if (Parser.getTok().is(AsmToken::Caret)) {
2802 Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
2803 Parser.Lex(); // Eat '^' token.
2804 }
2805
Bill Wendling2063b842010-11-18 23:43:05 +00002806 return false;
Kevin Enderbya2b99102009-10-09 21:12:28 +00002807}
2808
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002809// Helper function to parse the lane index for vector lists.
2810ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach04945c42011-12-02 00:35:16 +00002811parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2812 Index = 0; // Always return a defined index value.
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002813 if (Parser.getTok().is(AsmToken::LBrac)) {
2814 Parser.Lex(); // Eat the '['.
2815 if (Parser.getTok().is(AsmToken::RBrac)) {
2816 // "Dn[]" is the 'all lanes' syntax.
2817 LaneKind = AllLanes;
2818 Parser.Lex(); // Eat the ']'.
2819 return MatchOperand_Success;
2820 }
Jim Grosbach7de7ab82011-12-21 01:19:23 +00002821 const MCExpr *LaneIndex;
2822 SMLoc Loc = Parser.getTok().getLoc();
2823 if (getParser().ParseExpression(LaneIndex)) {
2824 Error(Loc, "illegal expression");
2825 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00002826 }
Jim Grosbach7de7ab82011-12-21 01:19:23 +00002827 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LaneIndex);
2828 if (!CE) {
2829 Error(Loc, "lane index must be empty or an integer");
2830 return MatchOperand_ParseFail;
2831 }
2832 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2833 Error(Parser.getTok().getLoc(), "']' expected");
2834 return MatchOperand_ParseFail;
2835 }
2836 Parser.Lex(); // Eat the ']'.
2837 int64_t Val = CE->getValue();
2838
2839 // FIXME: Make this range check context sensitive for .8, .16, .32.
2840 if (Val < 0 || Val > 7) {
2841 Error(Parser.getTok().getLoc(), "lane index out of range");
2842 return MatchOperand_ParseFail;
2843 }
2844 Index = Val;
2845 LaneKind = IndexedLane;
2846 return MatchOperand_Success;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002847 }
2848 LaneKind = NoLanes;
2849 return MatchOperand_Success;
2850}
2851
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002852// parse a vector register list
2853ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2854parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002855 VectorLaneTy LaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00002856 unsigned LaneIndex;
Jim Grosbach8d579232011-11-15 21:45:55 +00002857 SMLoc S = Parser.getTok().getLoc();
2858 // As an extension (to match gas), support a plain D register or Q register
2859 // (without encosing curly braces) as a single or double entry list,
2860 // respectively.
2861 if (Parser.getTok().is(AsmToken::Identifier)) {
2862 int Reg = tryParseRegister();
2863 if (Reg == -1)
2864 return MatchOperand_NoMatch;
2865 SMLoc E = Parser.getTok().getLoc();
2866 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach04945c42011-12-02 00:35:16 +00002867 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002868 if (Res != MatchOperand_Success)
2869 return Res;
2870 switch (LaneKind) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002871 case NoLanes:
2872 E = Parser.getTok().getLoc();
Jim Grosbach2f50e922011-12-15 21:44:33 +00002873 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002874 break;
2875 case AllLanes:
2876 E = Parser.getTok().getLoc();
Jim Grosbachc5af54e2011-12-21 00:38:54 +00002877 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false,
2878 S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002879 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00002880 case IndexedLane:
2881 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
Jim Grosbach75e2ab52011-12-20 19:21:26 +00002882 LaneIndex,
2883 false, S, E));
Jim Grosbach04945c42011-12-02 00:35:16 +00002884 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002885 }
Jim Grosbach8d579232011-11-15 21:45:55 +00002886 return MatchOperand_Success;
2887 }
2888 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2889 Reg = getDRegFromQReg(Reg);
Jim Grosbach04945c42011-12-02 00:35:16 +00002890 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002891 if (Res != MatchOperand_Success)
2892 return Res;
2893 switch (LaneKind) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002894 case NoLanes:
2895 E = Parser.getTok().getLoc();
Jim Grosbach2f50e922011-12-15 21:44:33 +00002896 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002897 break;
2898 case AllLanes:
2899 E = Parser.getTok().getLoc();
Jim Grosbachc5af54e2011-12-21 00:38:54 +00002900 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, false,
2901 S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002902 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00002903 case IndexedLane:
2904 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
Jim Grosbach75e2ab52011-12-20 19:21:26 +00002905 LaneIndex,
2906 false, S, E));
Jim Grosbach04945c42011-12-02 00:35:16 +00002907 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002908 }
Jim Grosbach8d579232011-11-15 21:45:55 +00002909 return MatchOperand_Success;
2910 }
2911 Error(S, "vector register expected");
2912 return MatchOperand_ParseFail;
2913 }
2914
2915 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002916 return MatchOperand_NoMatch;
2917
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002918 Parser.Lex(); // Eat '{' token.
2919 SMLoc RegLoc = Parser.getTok().getLoc();
2920
2921 int Reg = tryParseRegister();
2922 if (Reg == -1) {
2923 Error(RegLoc, "register expected");
2924 return MatchOperand_ParseFail;
2925 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002926 unsigned Count = 1;
Jim Grosbachc2f16a32011-12-15 21:54:55 +00002927 int Spacing = 0;
Jim Grosbach080a4992011-10-28 00:06:50 +00002928 unsigned FirstReg = Reg;
2929 // The list is of D registers, but we also allow Q regs and just interpret
2930 // them as the two D sub-registers.
2931 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2932 FirstReg = Reg = getDRegFromQReg(Reg);
Jim Grosbach2f50e922011-12-15 21:44:33 +00002933 Spacing = 1; // double-spacing requires explicit D registers, otherwise
2934 // it's ambiguous with four-register single spaced.
Jim Grosbach080a4992011-10-28 00:06:50 +00002935 ++Reg;
2936 ++Count;
2937 }
Jim Grosbach04945c42011-12-02 00:35:16 +00002938 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002939 return MatchOperand_ParseFail;
Jim Grosbach080a4992011-10-28 00:06:50 +00002940
Jim Grosbache891fe82011-11-15 23:19:15 +00002941 while (Parser.getTok().is(AsmToken::Comma) ||
2942 Parser.getTok().is(AsmToken::Minus)) {
2943 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbach2f50e922011-12-15 21:44:33 +00002944 if (!Spacing)
2945 Spacing = 1; // Register range implies a single spaced list.
2946 else if (Spacing == 2) {
2947 Error(Parser.getTok().getLoc(),
2948 "sequential registers in double spaced list");
2949 return MatchOperand_ParseFail;
2950 }
Jim Grosbache891fe82011-11-15 23:19:15 +00002951 Parser.Lex(); // Eat the minus.
2952 SMLoc EndLoc = Parser.getTok().getLoc();
2953 int EndReg = tryParseRegister();
2954 if (EndReg == -1) {
2955 Error(EndLoc, "register expected");
2956 return MatchOperand_ParseFail;
2957 }
2958 // Allow Q regs and just interpret them as the two D sub-registers.
2959 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2960 EndReg = getDRegFromQReg(EndReg) + 1;
2961 // If the register is the same as the start reg, there's nothing
2962 // more to do.
2963 if (Reg == EndReg)
2964 continue;
2965 // The register must be in the same register class as the first.
2966 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
2967 Error(EndLoc, "invalid register in register list");
2968 return MatchOperand_ParseFail;
2969 }
2970 // Ranges must go from low to high.
2971 if (Reg > EndReg) {
2972 Error(EndLoc, "bad range in register list");
2973 return MatchOperand_ParseFail;
2974 }
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002975 // Parse the lane specifier if present.
2976 VectorLaneTy NextLaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00002977 unsigned NextLaneIndex;
2978 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002979 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00002980 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002981 Error(EndLoc, "mismatched lane index in register list");
2982 return MatchOperand_ParseFail;
2983 }
2984 EndLoc = Parser.getTok().getLoc();
Jim Grosbache891fe82011-11-15 23:19:15 +00002985
2986 // Add all the registers in the range to the register list.
2987 Count += EndReg - Reg;
2988 Reg = EndReg;
2989 continue;
2990 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002991 Parser.Lex(); // Eat the comma.
2992 RegLoc = Parser.getTok().getLoc();
2993 int OldReg = Reg;
2994 Reg = tryParseRegister();
2995 if (Reg == -1) {
2996 Error(RegLoc, "register expected");
2997 return MatchOperand_ParseFail;
2998 }
Jim Grosbach080a4992011-10-28 00:06:50 +00002999 // vector register lists must be contiguous.
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003000 // It's OK to use the enumeration values directly here rather, as the
3001 // VFP register classes have the enum sorted properly.
Jim Grosbach080a4992011-10-28 00:06:50 +00003002 //
3003 // The list is of D registers, but we also allow Q regs and just interpret
3004 // them as the two D sub-registers.
3005 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
Jim Grosbach2f50e922011-12-15 21:44:33 +00003006 if (!Spacing)
3007 Spacing = 1; // Register range implies a single spaced list.
3008 else if (Spacing == 2) {
3009 Error(RegLoc,
3010 "invalid register in double-spaced list (must be 'D' register')");
3011 return MatchOperand_ParseFail;
3012 }
Jim Grosbach080a4992011-10-28 00:06:50 +00003013 Reg = getDRegFromQReg(Reg);
3014 if (Reg != OldReg + 1) {
3015 Error(RegLoc, "non-contiguous register range");
3016 return MatchOperand_ParseFail;
3017 }
3018 ++Reg;
3019 Count += 2;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003020 // Parse the lane specifier if present.
3021 VectorLaneTy NextLaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00003022 unsigned NextLaneIndex;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003023 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach04945c42011-12-02 00:35:16 +00003024 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003025 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00003026 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003027 Error(EndLoc, "mismatched lane index in register list");
3028 return MatchOperand_ParseFail;
3029 }
Jim Grosbach080a4992011-10-28 00:06:50 +00003030 continue;
3031 }
Jim Grosbach2f50e922011-12-15 21:44:33 +00003032 // Normal D register.
3033 // Figure out the register spacing (single or double) of the list if
3034 // we don't know it already.
3035 if (!Spacing)
3036 Spacing = 1 + (Reg == OldReg + 2);
3037
3038 // Just check that it's contiguous and keep going.
3039 if (Reg != OldReg + Spacing) {
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003040 Error(RegLoc, "non-contiguous register range");
3041 return MatchOperand_ParseFail;
3042 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003043 ++Count;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003044 // Parse the lane specifier if present.
3045 VectorLaneTy NextLaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00003046 unsigned NextLaneIndex;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003047 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach04945c42011-12-02 00:35:16 +00003048 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003049 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00003050 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003051 Error(EndLoc, "mismatched lane index in register list");
3052 return MatchOperand_ParseFail;
3053 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003054 }
3055
3056 SMLoc E = Parser.getTok().getLoc();
3057 if (Parser.getTok().isNot(AsmToken::RCurly)) {
3058 Error(E, "'}' expected");
3059 return MatchOperand_ParseFail;
3060 }
3061 Parser.Lex(); // Eat '}' token.
3062
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003063 switch (LaneKind) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003064 case NoLanes:
Jim Grosbach2f50e922011-12-15 21:44:33 +00003065 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count,
3066 (Spacing == 2), S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003067 break;
3068 case AllLanes:
3069 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
Jim Grosbachc5af54e2011-12-21 00:38:54 +00003070 (Spacing == 2),
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003071 S, E));
3072 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00003073 case IndexedLane:
3074 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
Jim Grosbach75e2ab52011-12-20 19:21:26 +00003075 LaneIndex,
3076 (Spacing == 2),
3077 S, E));
Jim Grosbach04945c42011-12-02 00:35:16 +00003078 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003079 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003080 return MatchOperand_Success;
3081}
3082
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003083/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbach861e49c2011-02-12 01:34:40 +00003084ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003085parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003086 SMLoc S = Parser.getTok().getLoc();
3087 const AsmToken &Tok = Parser.getTok();
3088 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3089 StringRef OptStr = Tok.getString();
3090
3091 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
3092 .Case("sy", ARM_MB::SY)
3093 .Case("st", ARM_MB::ST)
Jim Grosbach44c3f082011-07-13 23:40:38 +00003094 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003095 .Case("ish", ARM_MB::ISH)
Jim Grosbach44c3f082011-07-13 23:40:38 +00003096 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003097 .Case("ishst", ARM_MB::ISHST)
3098 .Case("nsh", ARM_MB::NSH)
Jim Grosbach44c3f082011-07-13 23:40:38 +00003099 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003100 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach44c3f082011-07-13 23:40:38 +00003101 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003102 .Case("osh", ARM_MB::OSH)
3103 .Case("oshst", ARM_MB::OSHST)
3104 .Default(~0U);
3105
3106 if (Opt == ~0U)
Jim Grosbach861e49c2011-02-12 01:34:40 +00003107 return MatchOperand_NoMatch;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003108
3109 Parser.Lex(); // Eat identifier token.
3110 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00003111 return MatchOperand_Success;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003112}
3113
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003114/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003115ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003116parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003117 SMLoc S = Parser.getTok().getLoc();
3118 const AsmToken &Tok = Parser.getTok();
3119 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3120 StringRef IFlagsStr = Tok.getString();
3121
Owen Anderson10c5b122011-10-05 17:16:40 +00003122 // An iflags string of "none" is interpreted to mean that none of the AIF
3123 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003124 unsigned IFlags = 0;
Owen Anderson10c5b122011-10-05 17:16:40 +00003125 if (IFlagsStr != "none") {
3126 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
3127 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
3128 .Case("a", ARM_PROC::A)
3129 .Case("i", ARM_PROC::I)
3130 .Case("f", ARM_PROC::F)
3131 .Default(~0U);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003132
Owen Anderson10c5b122011-10-05 17:16:40 +00003133 // If some specific iflag is already set, it means that some letter is
3134 // present more than once, this is not acceptable.
3135 if (Flag == ~0U || (IFlags & Flag))
3136 return MatchOperand_NoMatch;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003137
Owen Anderson10c5b122011-10-05 17:16:40 +00003138 IFlags |= Flag;
3139 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003140 }
3141
3142 Parser.Lex(); // Eat identifier token.
3143 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
3144 return MatchOperand_Success;
3145}
3146
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003147/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003148ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003149parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003150 SMLoc S = Parser.getTok().getLoc();
3151 const AsmToken &Tok = Parser.getTok();
3152 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3153 StringRef Mask = Tok.getString();
3154
James Molloy21efa7d2011-09-28 14:21:38 +00003155 if (isMClass()) {
3156 // See ARMv6-M 10.1.1
3157 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
3158 .Case("apsr", 0)
3159 .Case("iapsr", 1)
3160 .Case("eapsr", 2)
3161 .Case("xpsr", 3)
3162 .Case("ipsr", 5)
3163 .Case("epsr", 6)
3164 .Case("iepsr", 7)
3165 .Case("msp", 8)
3166 .Case("psp", 9)
3167 .Case("primask", 16)
3168 .Case("basepri", 17)
3169 .Case("basepri_max", 18)
3170 .Case("faultmask", 19)
3171 .Case("control", 20)
3172 .Default(~0U);
Jim Grosbach3794d822011-12-22 17:17:10 +00003173
James Molloy21efa7d2011-09-28 14:21:38 +00003174 if (FlagsVal == ~0U)
3175 return MatchOperand_NoMatch;
3176
3177 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
3178 // basepri, basepri_max and faultmask only valid for V7m.
3179 return MatchOperand_NoMatch;
Jim Grosbach3794d822011-12-22 17:17:10 +00003180
James Molloy21efa7d2011-09-28 14:21:38 +00003181 Parser.Lex(); // Eat identifier token.
3182 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3183 return MatchOperand_Success;
3184 }
3185
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003186 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
3187 size_t Start = 0, Next = Mask.find('_');
3188 StringRef Flags = "";
Benjamin Kramer20baffb2011-11-06 20:37:06 +00003189 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003190 if (Next != StringRef::npos)
3191 Flags = Mask.slice(Next+1, Mask.size());
3192
3193 // FlagsVal contains the complete mask:
3194 // 3-0: Mask
3195 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3196 unsigned FlagsVal = 0;
3197
3198 if (SpecReg == "apsr") {
3199 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachd25c2cd2011-07-19 22:45:10 +00003200 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003201 .Case("g", 0x4) // same as CPSR_s
3202 .Case("nzcvqg", 0xc) // same as CPSR_fs
3203 .Default(~0U);
3204
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00003205 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003206 if (!Flags.empty())
3207 return MatchOperand_NoMatch;
3208 else
Jim Grosbach0ecd3952011-09-14 20:03:46 +00003209 FlagsVal = 8; // No flag
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00003210 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003211 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes54452132011-05-25 00:35:03 +00003212 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
3213 Flags = "fc";
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003214 for (int i = 0, e = Flags.size(); i != e; ++i) {
3215 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
3216 .Case("c", 1)
3217 .Case("x", 2)
3218 .Case("s", 4)
3219 .Case("f", 8)
3220 .Default(~0U);
3221
3222 // If some specific flag is already set, it means that some letter is
3223 // present more than once, this is not acceptable.
3224 if (FlagsVal == ~0U || (FlagsVal & Flag))
3225 return MatchOperand_NoMatch;
3226 FlagsVal |= Flag;
3227 }
3228 } else // No match for special register.
3229 return MatchOperand_NoMatch;
3230
Owen Anderson03a173e2011-10-21 18:43:28 +00003231 // Special register without flags is NOT equivalent to "fc" flags.
3232 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3233 // two lines would enable gas compatibility at the expense of breaking
3234 // round-tripping.
3235 //
3236 // if (!FlagsVal)
3237 // FlagsVal = 0x9;
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003238
3239 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3240 if (SpecReg == "spsr")
3241 FlagsVal |= 16;
3242
3243 Parser.Lex(); // Eat identifier token.
3244 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3245 return MatchOperand_Success;
3246}
3247
Jim Grosbach27c1e252011-07-21 17:23:04 +00003248ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3249parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3250 int Low, int High) {
3251 const AsmToken &Tok = Parser.getTok();
3252 if (Tok.isNot(AsmToken::Identifier)) {
3253 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3254 return MatchOperand_ParseFail;
3255 }
3256 StringRef ShiftName = Tok.getString();
Benjamin Kramer20baffb2011-11-06 20:37:06 +00003257 std::string LowerOp = Op.lower();
3258 std::string UpperOp = Op.upper();
Jim Grosbach27c1e252011-07-21 17:23:04 +00003259 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3260 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3261 return MatchOperand_ParseFail;
3262 }
3263 Parser.Lex(); // Eat shift type token.
3264
3265 // There must be a '#' and a shift amount.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003266 if (Parser.getTok().isNot(AsmToken::Hash) &&
3267 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach27c1e252011-07-21 17:23:04 +00003268 Error(Parser.getTok().getLoc(), "'#' expected");
3269 return MatchOperand_ParseFail;
3270 }
3271 Parser.Lex(); // Eat hash token.
3272
3273 const MCExpr *ShiftAmount;
3274 SMLoc Loc = Parser.getTok().getLoc();
3275 if (getParser().ParseExpression(ShiftAmount)) {
3276 Error(Loc, "illegal expression");
3277 return MatchOperand_ParseFail;
3278 }
3279 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3280 if (!CE) {
3281 Error(Loc, "constant expression expected");
3282 return MatchOperand_ParseFail;
3283 }
3284 int Val = CE->getValue();
3285 if (Val < Low || Val > High) {
3286 Error(Loc, "immediate value out of range");
3287 return MatchOperand_ParseFail;
3288 }
3289
3290 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3291
3292 return MatchOperand_Success;
3293}
3294
Jim Grosbach0a547702011-07-22 17:44:50 +00003295ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3296parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3297 const AsmToken &Tok = Parser.getTok();
3298 SMLoc S = Tok.getLoc();
3299 if (Tok.isNot(AsmToken::Identifier)) {
3300 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3301 return MatchOperand_ParseFail;
3302 }
3303 int Val = StringSwitch<int>(Tok.getString())
3304 .Case("be", 1)
3305 .Case("le", 0)
3306 .Default(-1);
3307 Parser.Lex(); // Eat the token.
3308
3309 if (Val == -1) {
3310 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3311 return MatchOperand_ParseFail;
3312 }
3313 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3314 getContext()),
3315 S, Parser.getTok().getLoc()));
3316 return MatchOperand_Success;
3317}
3318
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00003319/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3320/// instructions. Legal values are:
3321/// lsl #n 'n' in [0,31]
3322/// asr #n 'n' in [1,32]
3323/// n == 32 encoded as n == 0.
3324ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3325parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3326 const AsmToken &Tok = Parser.getTok();
3327 SMLoc S = Tok.getLoc();
3328 if (Tok.isNot(AsmToken::Identifier)) {
3329 Error(S, "shift operator 'asr' or 'lsl' expected");
3330 return MatchOperand_ParseFail;
3331 }
3332 StringRef ShiftName = Tok.getString();
3333 bool isASR;
3334 if (ShiftName == "lsl" || ShiftName == "LSL")
3335 isASR = false;
3336 else if (ShiftName == "asr" || ShiftName == "ASR")
3337 isASR = true;
3338 else {
3339 Error(S, "shift operator 'asr' or 'lsl' expected");
3340 return MatchOperand_ParseFail;
3341 }
3342 Parser.Lex(); // Eat the operator.
3343
3344 // A '#' and a shift amount.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003345 if (Parser.getTok().isNot(AsmToken::Hash) &&
3346 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00003347 Error(Parser.getTok().getLoc(), "'#' expected");
3348 return MatchOperand_ParseFail;
3349 }
3350 Parser.Lex(); // Eat hash token.
3351
3352 const MCExpr *ShiftAmount;
3353 SMLoc E = Parser.getTok().getLoc();
3354 if (getParser().ParseExpression(ShiftAmount)) {
3355 Error(E, "malformed shift expression");
3356 return MatchOperand_ParseFail;
3357 }
3358 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3359 if (!CE) {
3360 Error(E, "shift amount must be an immediate");
3361 return MatchOperand_ParseFail;
3362 }
3363
3364 int64_t Val = CE->getValue();
3365 if (isASR) {
3366 // Shift amount must be in [1,32]
3367 if (Val < 1 || Val > 32) {
3368 Error(E, "'asr' shift amount must be in range [1,32]");
3369 return MatchOperand_ParseFail;
3370 }
Owen Andersonf01e2de2011-09-26 21:06:22 +00003371 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3372 if (isThumb() && Val == 32) {
3373 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3374 return MatchOperand_ParseFail;
3375 }
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00003376 if (Val == 32) Val = 0;
3377 } else {
3378 // Shift amount must be in [1,32]
3379 if (Val < 0 || Val > 31) {
3380 Error(E, "'lsr' shift amount must be in range [0,31]");
3381 return MatchOperand_ParseFail;
3382 }
3383 }
3384
3385 E = Parser.getTok().getLoc();
3386 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3387
3388 return MatchOperand_Success;
3389}
3390
Jim Grosbach833b9d32011-07-27 20:15:40 +00003391/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3392/// of instructions. Legal values are:
3393/// ror #n 'n' in {0, 8, 16, 24}
3394ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3395parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3396 const AsmToken &Tok = Parser.getTok();
3397 SMLoc S = Tok.getLoc();
Jim Grosbach82213192011-09-19 20:29:33 +00003398 if (Tok.isNot(AsmToken::Identifier))
3399 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00003400 StringRef ShiftName = Tok.getString();
Jim Grosbach82213192011-09-19 20:29:33 +00003401 if (ShiftName != "ror" && ShiftName != "ROR")
3402 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00003403 Parser.Lex(); // Eat the operator.
3404
3405 // A '#' and a rotate amount.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003406 if (Parser.getTok().isNot(AsmToken::Hash) &&
3407 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach833b9d32011-07-27 20:15:40 +00003408 Error(Parser.getTok().getLoc(), "'#' expected");
3409 return MatchOperand_ParseFail;
3410 }
3411 Parser.Lex(); // Eat hash token.
3412
3413 const MCExpr *ShiftAmount;
3414 SMLoc E = Parser.getTok().getLoc();
3415 if (getParser().ParseExpression(ShiftAmount)) {
3416 Error(E, "malformed rotate expression");
3417 return MatchOperand_ParseFail;
3418 }
3419 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3420 if (!CE) {
3421 Error(E, "rotate amount must be an immediate");
3422 return MatchOperand_ParseFail;
3423 }
3424
3425 int64_t Val = CE->getValue();
3426 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3427 // normally, zero is represented in asm by omitting the rotate operand
3428 // entirely.
3429 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3430 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3431 return MatchOperand_ParseFail;
3432 }
3433
3434 E = Parser.getTok().getLoc();
3435 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3436
3437 return MatchOperand_Success;
3438}
3439
Jim Grosbach864b6092011-07-28 21:34:26 +00003440ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3441parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3442 SMLoc S = Parser.getTok().getLoc();
3443 // The bitfield descriptor is really two operands, the LSB and the width.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003444 if (Parser.getTok().isNot(AsmToken::Hash) &&
3445 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach864b6092011-07-28 21:34:26 +00003446 Error(Parser.getTok().getLoc(), "'#' expected");
3447 return MatchOperand_ParseFail;
3448 }
3449 Parser.Lex(); // Eat hash token.
3450
3451 const MCExpr *LSBExpr;
3452 SMLoc E = Parser.getTok().getLoc();
3453 if (getParser().ParseExpression(LSBExpr)) {
3454 Error(E, "malformed immediate expression");
3455 return MatchOperand_ParseFail;
3456 }
3457 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3458 if (!CE) {
3459 Error(E, "'lsb' operand must be an immediate");
3460 return MatchOperand_ParseFail;
3461 }
3462
3463 int64_t LSB = CE->getValue();
3464 // The LSB must be in the range [0,31]
3465 if (LSB < 0 || LSB > 31) {
3466 Error(E, "'lsb' operand must be in the range [0,31]");
3467 return MatchOperand_ParseFail;
3468 }
3469 E = Parser.getTok().getLoc();
3470
3471 // Expect another immediate operand.
3472 if (Parser.getTok().isNot(AsmToken::Comma)) {
3473 Error(Parser.getTok().getLoc(), "too few operands");
3474 return MatchOperand_ParseFail;
3475 }
3476 Parser.Lex(); // Eat hash token.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003477 if (Parser.getTok().isNot(AsmToken::Hash) &&
3478 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach864b6092011-07-28 21:34:26 +00003479 Error(Parser.getTok().getLoc(), "'#' expected");
3480 return MatchOperand_ParseFail;
3481 }
3482 Parser.Lex(); // Eat hash token.
3483
3484 const MCExpr *WidthExpr;
3485 if (getParser().ParseExpression(WidthExpr)) {
3486 Error(E, "malformed immediate expression");
3487 return MatchOperand_ParseFail;
3488 }
3489 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3490 if (!CE) {
3491 Error(E, "'width' operand must be an immediate");
3492 return MatchOperand_ParseFail;
3493 }
3494
3495 int64_t Width = CE->getValue();
3496 // The LSB must be in the range [1,32-lsb]
3497 if (Width < 1 || Width > 32 - LSB) {
3498 Error(E, "'width' operand must be in the range [1,32-lsb]");
3499 return MatchOperand_ParseFail;
3500 }
3501 E = Parser.getTok().getLoc();
3502
3503 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3504
3505 return MatchOperand_Success;
3506}
3507
Jim Grosbachd3595712011-08-03 23:50:40 +00003508ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3509parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3510 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachc320c852011-08-05 21:28:30 +00003511 // postidx_reg := '+' register {, shift}
3512 // | '-' register {, shift}
3513 // | register {, shift}
Jim Grosbachd3595712011-08-03 23:50:40 +00003514
3515 // This method must return MatchOperand_NoMatch without consuming any tokens
3516 // in the case where there is no match, as other alternatives take other
3517 // parse methods.
3518 AsmToken Tok = Parser.getTok();
3519 SMLoc S = Tok.getLoc();
3520 bool haveEaten = false;
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00003521 bool isAdd = true;
Jim Grosbachd3595712011-08-03 23:50:40 +00003522 int Reg = -1;
3523 if (Tok.is(AsmToken::Plus)) {
3524 Parser.Lex(); // Eat the '+' token.
3525 haveEaten = true;
3526 } else if (Tok.is(AsmToken::Minus)) {
3527 Parser.Lex(); // Eat the '-' token.
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00003528 isAdd = false;
Jim Grosbachd3595712011-08-03 23:50:40 +00003529 haveEaten = true;
3530 }
3531 if (Parser.getTok().is(AsmToken::Identifier))
3532 Reg = tryParseRegister();
3533 if (Reg == -1) {
3534 if (!haveEaten)
3535 return MatchOperand_NoMatch;
3536 Error(Parser.getTok().getLoc(), "register expected");
3537 return MatchOperand_ParseFail;
3538 }
3539 SMLoc E = Parser.getTok().getLoc();
3540
Jim Grosbachc320c852011-08-05 21:28:30 +00003541 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3542 unsigned ShiftImm = 0;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00003543 if (Parser.getTok().is(AsmToken::Comma)) {
3544 Parser.Lex(); // Eat the ','.
3545 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3546 return MatchOperand_ParseFail;
3547 }
Jim Grosbachc320c852011-08-05 21:28:30 +00003548
3549 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3550 ShiftImm, S, E));
Jim Grosbachd3595712011-08-03 23:50:40 +00003551
3552 return MatchOperand_Success;
3553}
3554
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00003555ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3556parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3557 // Check for a post-index addressing register operand. Specifically:
3558 // am3offset := '+' register
3559 // | '-' register
3560 // | register
3561 // | # imm
3562 // | # + imm
3563 // | # - imm
3564
3565 // This method must return MatchOperand_NoMatch without consuming any tokens
3566 // in the case where there is no match, as other alternatives take other
3567 // parse methods.
3568 AsmToken Tok = Parser.getTok();
3569 SMLoc S = Tok.getLoc();
3570
3571 // Do immediates first, as we always parse those if we have a '#'.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003572 if (Parser.getTok().is(AsmToken::Hash) ||
3573 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00003574 Parser.Lex(); // Eat the '#'.
3575 // Explicitly look for a '-', as we need to encode negative zero
3576 // differently.
3577 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3578 const MCExpr *Offset;
3579 if (getParser().ParseExpression(Offset))
3580 return MatchOperand_ParseFail;
3581 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3582 if (!CE) {
3583 Error(S, "constant expression expected");
3584 return MatchOperand_ParseFail;
3585 }
3586 SMLoc E = Tok.getLoc();
3587 // Negative zero is encoded as the flag value INT32_MIN.
3588 int32_t Val = CE->getValue();
3589 if (isNegative && Val == 0)
3590 Val = INT32_MIN;
3591
3592 Operands.push_back(
3593 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3594
3595 return MatchOperand_Success;
3596 }
3597
3598
3599 bool haveEaten = false;
3600 bool isAdd = true;
3601 int Reg = -1;
3602 if (Tok.is(AsmToken::Plus)) {
3603 Parser.Lex(); // Eat the '+' token.
3604 haveEaten = true;
3605 } else if (Tok.is(AsmToken::Minus)) {
3606 Parser.Lex(); // Eat the '-' token.
3607 isAdd = false;
3608 haveEaten = true;
3609 }
3610 if (Parser.getTok().is(AsmToken::Identifier))
3611 Reg = tryParseRegister();
3612 if (Reg == -1) {
3613 if (!haveEaten)
3614 return MatchOperand_NoMatch;
3615 Error(Parser.getTok().getLoc(), "register expected");
3616 return MatchOperand_ParseFail;
3617 }
3618 SMLoc E = Parser.getTok().getLoc();
3619
3620 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3621 0, S, E));
3622
3623 return MatchOperand_Success;
3624}
3625
Jim Grosbach7db8d692011-09-08 22:07:06 +00003626/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3627/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3628/// when they refer multiple MIOperands inside a single one.
3629bool ARMAsmParser::
3630cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3631 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3632 // Rt, Rt2
3633 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3634 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3635 // Create a writeback register dummy placeholder.
3636 Inst.addOperand(MCOperand::CreateReg(0));
3637 // addr
3638 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3639 // pred
3640 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3641 return true;
3642}
3643
3644/// cvtT2StrdPre - Convert parsed operands to MCInst.
3645/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3646/// when they refer multiple MIOperands inside a single one.
3647bool ARMAsmParser::
3648cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3649 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3650 // Create a writeback register dummy placeholder.
3651 Inst.addOperand(MCOperand::CreateReg(0));
3652 // Rt, Rt2
3653 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3654 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3655 // addr
3656 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3657 // pred
3658 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3659 return true;
3660}
3661
Jim Grosbachc086f682011-09-08 00:39:19 +00003662/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3663/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3664/// when they refer multiple MIOperands inside a single one.
3665bool ARMAsmParser::
3666cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3667 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3668 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3669
3670 // Create a writeback register dummy placeholder.
3671 Inst.addOperand(MCOperand::CreateImm(0));
3672
3673 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3674 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3675 return true;
3676}
3677
Jim Grosbach9c0b86a2011-09-16 21:55:56 +00003678/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3679/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3680/// when they refer multiple MIOperands inside a single one.
3681bool ARMAsmParser::
3682cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3683 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3684 // Create a writeback register dummy placeholder.
3685 Inst.addOperand(MCOperand::CreateImm(0));
3686 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3687 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3688 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3689 return true;
3690}
3691
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003692/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003693/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3694/// when they refer multiple MIOperands inside a single one.
3695bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003696cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003697 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3698 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3699
3700 // Create a writeback register dummy placeholder.
3701 Inst.addOperand(MCOperand::CreateImm(0));
3702
Jim Grosbachd3595712011-08-03 23:50:40 +00003703 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003704 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3705 return true;
3706}
3707
Owen Anderson16d33f32011-08-26 20:43:14 +00003708/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3709/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3710/// when they refer multiple MIOperands inside a single one.
3711bool ARMAsmParser::
3712cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3713 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3714 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3715
3716 // Create a writeback register dummy placeholder.
3717 Inst.addOperand(MCOperand::CreateImm(0));
3718
3719 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3720 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3721 return true;
3722}
3723
3724
Jim Grosbachd564bf32011-08-11 19:22:40 +00003725/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3726/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3727/// when they refer multiple MIOperands inside a single one.
3728bool ARMAsmParser::
3729cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3730 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3731 // Create a writeback register dummy placeholder.
3732 Inst.addOperand(MCOperand::CreateImm(0));
3733 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3734 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3735 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3736 return true;
3737}
3738
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003739/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003740/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3741/// when they refer multiple MIOperands inside a single one.
3742bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003743cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003744 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3745 // Create a writeback register dummy placeholder.
3746 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd564bf32011-08-11 19:22:40 +00003747 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3748 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3749 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbachd3595712011-08-03 23:50:40 +00003750 return true;
3751}
3752
Jim Grosbachd886f8c2011-08-11 21:17:22 +00003753/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3754/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3755/// when they refer multiple MIOperands inside a single one.
3756bool ARMAsmParser::
3757cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3758 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3759 // Create a writeback register dummy placeholder.
3760 Inst.addOperand(MCOperand::CreateImm(0));
3761 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3762 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3763 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3764 return true;
3765}
3766
Jim Grosbachd3595712011-08-03 23:50:40 +00003767/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3768/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3769/// when they refer multiple MIOperands inside a single one.
3770bool ARMAsmParser::
3771cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3772 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3773 // Rt
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003774 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbachd3595712011-08-03 23:50:40 +00003775 // Create a writeback register dummy placeholder.
3776 Inst.addOperand(MCOperand::CreateImm(0));
3777 // addr
3778 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3779 // offset
3780 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3781 // pred
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003782 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3783 return true;
3784}
3785
Jim Grosbachd3595712011-08-03 23:50:40 +00003786/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003787/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3788/// when they refer multiple MIOperands inside a single one.
3789bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003790cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3791 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3792 // Rt
Owen Andersonb0e68992011-07-28 17:18:57 +00003793 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003794 // Create a writeback register dummy placeholder.
3795 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd3595712011-08-03 23:50:40 +00003796 // addr
3797 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3798 // offset
3799 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3800 // pred
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003801 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3802 return true;
3803}
3804
Jim Grosbachd3595712011-08-03 23:50:40 +00003805/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003806/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3807/// when they refer multiple MIOperands inside a single one.
3808bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003809cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3810 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003811 // Create a writeback register dummy placeholder.
3812 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd3595712011-08-03 23:50:40 +00003813 // Rt
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003814 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbachd3595712011-08-03 23:50:40 +00003815 // addr
3816 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3817 // offset
3818 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3819 // pred
3820 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3821 return true;
3822}
3823
3824/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3825/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3826/// when they refer multiple MIOperands inside a single one.
3827bool ARMAsmParser::
3828cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3829 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3830 // Create a writeback register dummy placeholder.
3831 Inst.addOperand(MCOperand::CreateImm(0));
3832 // Rt
3833 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3834 // addr
3835 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3836 // offset
3837 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3838 // pred
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003839 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3840 return true;
3841}
3842
Jim Grosbach5b96b802011-08-10 20:29:19 +00003843/// cvtLdrdPre - Convert parsed operands to MCInst.
3844/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3845/// when they refer multiple MIOperands inside a single one.
3846bool ARMAsmParser::
3847cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3848 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3849 // Rt, Rt2
3850 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3851 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3852 // Create a writeback register dummy placeholder.
3853 Inst.addOperand(MCOperand::CreateImm(0));
3854 // addr
3855 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3856 // pred
3857 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3858 return true;
3859}
3860
Jim Grosbacheb09f492011-08-11 20:28:23 +00003861/// cvtStrdPre - Convert parsed operands to MCInst.
3862/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3863/// when they refer multiple MIOperands inside a single one.
3864bool ARMAsmParser::
3865cvtStrdPre(MCInst &Inst, unsigned Opcode,
3866 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3867 // Create a writeback register dummy placeholder.
3868 Inst.addOperand(MCOperand::CreateImm(0));
3869 // Rt, Rt2
3870 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3871 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3872 // addr
3873 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3874 // pred
3875 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3876 return true;
3877}
3878
Jim Grosbachcd4dd252011-08-10 22:42:16 +00003879/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3880/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3881/// when they refer multiple MIOperands inside a single one.
3882bool ARMAsmParser::
3883cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3884 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3885 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3886 // Create a writeback register dummy placeholder.
3887 Inst.addOperand(MCOperand::CreateImm(0));
3888 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3889 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3890 return true;
3891}
3892
Jim Grosbach8e048492011-08-19 22:07:46 +00003893/// cvtThumbMultiple- Convert parsed operands to MCInst.
3894/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3895/// when they refer multiple MIOperands inside a single one.
3896bool ARMAsmParser::
3897cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3898 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3899 // The second source operand must be the same register as the destination
3900 // operand.
3901 if (Operands.size() == 6 &&
Jim Grosbach459422d2011-08-19 22:30:46 +00003902 (((ARMOperand*)Operands[3])->getReg() !=
3903 ((ARMOperand*)Operands[5])->getReg()) &&
3904 (((ARMOperand*)Operands[3])->getReg() !=
3905 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach8e048492011-08-19 22:07:46 +00003906 Error(Operands[3]->getStartLoc(),
Jim Grosbach459422d2011-08-19 22:30:46 +00003907 "destination register must match source register");
Jim Grosbach8e048492011-08-19 22:07:46 +00003908 return false;
3909 }
3910 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3911 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach5a5ce632011-11-10 22:10:12 +00003912 // If we have a three-operand form, make sure to set Rn to be the operand
3913 // that isn't the same as Rd.
3914 unsigned RegOp = 4;
3915 if (Operands.size() == 6 &&
3916 ((ARMOperand*)Operands[4])->getReg() ==
3917 ((ARMOperand*)Operands[3])->getReg())
3918 RegOp = 5;
3919 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
3920 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach8e048492011-08-19 22:07:46 +00003921 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3922
3923 return true;
3924}
Jim Grosbachcd4dd252011-08-10 22:42:16 +00003925
Jim Grosbach3ea06572011-10-24 22:16:58 +00003926bool ARMAsmParser::
3927cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3928 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3929 // Vd
Jim Grosbach182b6a02011-11-29 23:51:09 +00003930 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach3ea06572011-10-24 22:16:58 +00003931 // Create a writeback register dummy placeholder.
3932 Inst.addOperand(MCOperand::CreateImm(0));
3933 // Vn
3934 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3935 // pred
3936 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3937 return true;
3938}
3939
3940bool ARMAsmParser::
3941cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3942 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3943 // Vd
Jim Grosbach182b6a02011-11-29 23:51:09 +00003944 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach3ea06572011-10-24 22:16:58 +00003945 // Create a writeback register dummy placeholder.
3946 Inst.addOperand(MCOperand::CreateImm(0));
3947 // Vn
3948 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3949 // Vm
3950 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3951 // pred
3952 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3953 return true;
3954}
3955
Jim Grosbach05df4602011-10-31 21:50:31 +00003956bool ARMAsmParser::
3957cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
3958 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3959 // Create a writeback register dummy placeholder.
3960 Inst.addOperand(MCOperand::CreateImm(0));
3961 // Vn
3962 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3963 // Vt
Jim Grosbach182b6a02011-11-29 23:51:09 +00003964 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach05df4602011-10-31 21:50:31 +00003965 // pred
3966 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3967 return true;
3968}
3969
3970bool ARMAsmParser::
3971cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
3972 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3973 // Create a writeback register dummy placeholder.
3974 Inst.addOperand(MCOperand::CreateImm(0));
3975 // Vn
3976 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3977 // Vm
3978 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3979 // Vt
Jim Grosbach182b6a02011-11-29 23:51:09 +00003980 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach05df4602011-10-31 21:50:31 +00003981 // pred
3982 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3983 return true;
3984}
3985
Bill Wendlinge18980a2010-11-06 22:36:58 +00003986/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003987/// or an error. The first token must be a '[' when called.
Bill Wendling2063b842010-11-18 23:43:05 +00003988bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003989parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003990 SMLoc S, E;
Sean Callanan936b0d32010-01-19 21:44:56 +00003991 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00003992 "Token is not a Left Bracket");
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003993 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00003994 Parser.Lex(); // Eat left bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003995
Sean Callanan936b0d32010-01-19 21:44:56 +00003996 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003997 int BaseRegNum = tryParseRegister();
Jim Grosbachd3595712011-08-03 23:50:40 +00003998 if (BaseRegNum == -1)
3999 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004000
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00004001 // The next token must either be a comma or a closing bracket.
4002 const AsmToken &Tok = Parser.getTok();
4003 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbachd3595712011-08-03 23:50:40 +00004004 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00004005
Jim Grosbachd3595712011-08-03 23:50:40 +00004006 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004007 E = Tok.getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00004008 Parser.Lex(); // Eat right bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004009
Jim Grosbachd3595712011-08-03 23:50:40 +00004010 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbacha95ec992011-10-11 17:29:55 +00004011 0, 0, false, S, E));
Jim Grosbach32ff5582010-11-29 23:18:01 +00004012
Jim Grosbach40700e02011-09-19 18:42:21 +00004013 // If there's a pre-indexing writeback marker, '!', just add it as a token
4014 // operand. It's rather odd, but syntactically valid.
4015 if (Parser.getTok().is(AsmToken::Exclaim)) {
4016 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4017 Parser.Lex(); // Eat the '!'.
4018 }
4019
Jim Grosbachd3595712011-08-03 23:50:40 +00004020 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004021 }
Daniel Dunbarf5164f42011-01-18 05:34:24 +00004022
Jim Grosbachd3595712011-08-03 23:50:40 +00004023 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
4024 Parser.Lex(); // Eat the comma.
Daniel Dunbarf5164f42011-01-18 05:34:24 +00004025
Jim Grosbacha95ec992011-10-11 17:29:55 +00004026 // If we have a ':', it's an alignment specifier.
4027 if (Parser.getTok().is(AsmToken::Colon)) {
4028 Parser.Lex(); // Eat the ':'.
4029 E = Parser.getTok().getLoc();
4030
4031 const MCExpr *Expr;
4032 if (getParser().ParseExpression(Expr))
4033 return true;
4034
4035 // The expression has to be a constant. Memory references with relocations
4036 // don't come through here, as they use the <label> forms of the relevant
4037 // instructions.
4038 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4039 if (!CE)
4040 return Error (E, "constant expression expected");
4041
4042 unsigned Align = 0;
4043 switch (CE->getValue()) {
4044 default:
Jim Grosbachcef98cd2011-12-19 18:31:43 +00004045 return Error(E,
4046 "alignment specifier must be 16, 32, 64, 128, or 256 bits");
4047 case 16: Align = 2; break;
4048 case 32: Align = 4; break;
Jim Grosbacha95ec992011-10-11 17:29:55 +00004049 case 64: Align = 8; break;
4050 case 128: Align = 16; break;
4051 case 256: Align = 32; break;
4052 }
4053
4054 // Now we should have the closing ']'
4055 E = Parser.getTok().getLoc();
4056 if (Parser.getTok().isNot(AsmToken::RBrac))
4057 return Error(E, "']' expected");
4058 Parser.Lex(); // Eat right bracket token.
4059
4060 // Don't worry about range checking the value here. That's handled by
4061 // the is*() predicates.
4062 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
4063 ARM_AM::no_shift, 0, Align,
4064 false, S, E));
4065
4066 // If there's a pre-indexing writeback marker, '!', just add it as a token
4067 // operand.
4068 if (Parser.getTok().is(AsmToken::Exclaim)) {
4069 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4070 Parser.Lex(); // Eat the '!'.
4071 }
4072
4073 return false;
4074 }
4075
4076 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach8279c182011-11-15 22:14:41 +00004077 // offset. Be friendly and also accept a plain integer (without a leading
4078 // hash) for gas compatibility.
4079 if (Parser.getTok().is(AsmToken::Hash) ||
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004080 Parser.getTok().is(AsmToken::Dollar) ||
Jim Grosbach8279c182011-11-15 22:14:41 +00004081 Parser.getTok().is(AsmToken::Integer)) {
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004082 if (Parser.getTok().isNot(AsmToken::Integer))
Jim Grosbach8279c182011-11-15 22:14:41 +00004083 Parser.Lex(); // Eat the '#'.
Jim Grosbachd3595712011-08-03 23:50:40 +00004084 E = Parser.getTok().getLoc();
Daniel Dunbarf5164f42011-01-18 05:34:24 +00004085
Owen Anderson967674d2011-08-29 19:36:44 +00004086 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbachd3595712011-08-03 23:50:40 +00004087 const MCExpr *Offset;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004088 if (getParser().ParseExpression(Offset))
4089 return true;
Jim Grosbachd3595712011-08-03 23:50:40 +00004090
4091 // The expression has to be a constant. Memory references with relocations
4092 // don't come through here, as they use the <label> forms of the relevant
4093 // instructions.
4094 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
4095 if (!CE)
4096 return Error (E, "constant expression expected");
4097
Owen Anderson967674d2011-08-29 19:36:44 +00004098 // If the constant was #-0, represent it as INT32_MIN.
4099 int32_t Val = CE->getValue();
4100 if (isNegative && Val == 0)
4101 CE = MCConstantExpr::Create(INT32_MIN, getContext());
4102
Jim Grosbachd3595712011-08-03 23:50:40 +00004103 // Now we should have the closing ']'
4104 E = Parser.getTok().getLoc();
4105 if (Parser.getTok().isNot(AsmToken::RBrac))
4106 return Error(E, "']' expected");
4107 Parser.Lex(); // Eat right bracket token.
4108
4109 // Don't worry about range checking the value here. That's handled by
4110 // the is*() predicates.
4111 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbacha95ec992011-10-11 17:29:55 +00004112 ARM_AM::no_shift, 0, 0,
4113 false, S, E));
Jim Grosbachd3595712011-08-03 23:50:40 +00004114
4115 // If there's a pre-indexing writeback marker, '!', just add it as a token
4116 // operand.
4117 if (Parser.getTok().is(AsmToken::Exclaim)) {
4118 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4119 Parser.Lex(); // Eat the '!'.
4120 }
4121
4122 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004123 }
Jim Grosbachd3595712011-08-03 23:50:40 +00004124
4125 // The register offset is optionally preceded by a '+' or '-'
4126 bool isNegative = false;
4127 if (Parser.getTok().is(AsmToken::Minus)) {
4128 isNegative = true;
4129 Parser.Lex(); // Eat the '-'.
4130 } else if (Parser.getTok().is(AsmToken::Plus)) {
4131 // Nothing to do.
4132 Parser.Lex(); // Eat the '+'.
4133 }
4134
4135 E = Parser.getTok().getLoc();
4136 int OffsetRegNum = tryParseRegister();
4137 if (OffsetRegNum == -1)
4138 return Error(E, "register expected");
4139
4140 // If there's a shift operator, handle it.
4141 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00004142 unsigned ShiftImm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00004143 if (Parser.getTok().is(AsmToken::Comma)) {
4144 Parser.Lex(); // Eat the ','.
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00004145 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbachd3595712011-08-03 23:50:40 +00004146 return true;
4147 }
4148
4149 // Now we should have the closing ']'
4150 E = Parser.getTok().getLoc();
4151 if (Parser.getTok().isNot(AsmToken::RBrac))
4152 return Error(E, "']' expected");
4153 Parser.Lex(); // Eat right bracket token.
4154
4155 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbacha95ec992011-10-11 17:29:55 +00004156 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbachd3595712011-08-03 23:50:40 +00004157 S, E));
4158
Jim Grosbachc320c852011-08-05 21:28:30 +00004159 // If there's a pre-indexing writeback marker, '!', just add it as a token
4160 // operand.
4161 if (Parser.getTok().is(AsmToken::Exclaim)) {
4162 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4163 Parser.Lex(); // Eat the '!'.
4164 }
Jim Grosbachd3595712011-08-03 23:50:40 +00004165
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004166 return false;
4167}
4168
Jim Grosbachd3595712011-08-03 23:50:40 +00004169/// parseMemRegOffsetShift - one of these two:
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004170/// ( lsl | lsr | asr | ror ) , # shift_amount
4171/// rrx
Jim Grosbachd3595712011-08-03 23:50:40 +00004172/// return true if it parses a shift otherwise it returns false.
4173bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
4174 unsigned &Amount) {
4175 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan936b0d32010-01-19 21:44:56 +00004176 const AsmToken &Tok = Parser.getTok();
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004177 if (Tok.isNot(AsmToken::Identifier))
4178 return true;
Benjamin Kramer92d89982010-07-14 22:38:02 +00004179 StringRef ShiftName = Tok.getString();
Jim Grosbach3b559ff2011-12-07 23:40:58 +00004180 if (ShiftName == "lsl" || ShiftName == "LSL" ||
4181 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004182 St = ARM_AM::lsl;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004183 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004184 St = ARM_AM::lsr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004185 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004186 St = ARM_AM::asr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004187 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004188 St = ARM_AM::ror;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004189 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004190 St = ARM_AM::rrx;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004191 else
Jim Grosbachd3595712011-08-03 23:50:40 +00004192 return Error(Loc, "illegal shift operator");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004193 Parser.Lex(); // Eat shift type token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004194
Jim Grosbachd3595712011-08-03 23:50:40 +00004195 // rrx stands alone.
4196 Amount = 0;
4197 if (St != ARM_AM::rrx) {
4198 Loc = Parser.getTok().getLoc();
4199 // A '#' and a shift amount.
4200 const AsmToken &HashTok = Parser.getTok();
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004201 if (HashTok.isNot(AsmToken::Hash) &&
4202 HashTok.isNot(AsmToken::Dollar))
Jim Grosbachd3595712011-08-03 23:50:40 +00004203 return Error(HashTok.getLoc(), "'#' expected");
4204 Parser.Lex(); // Eat hash token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004205
Jim Grosbachd3595712011-08-03 23:50:40 +00004206 const MCExpr *Expr;
4207 if (getParser().ParseExpression(Expr))
4208 return true;
4209 // Range check the immediate.
4210 // lsl, ror: 0 <= imm <= 31
4211 // lsr, asr: 0 <= imm <= 32
4212 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4213 if (!CE)
4214 return Error(Loc, "shift amount must be an immediate");
4215 int64_t Imm = CE->getValue();
4216 if (Imm < 0 ||
4217 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4218 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4219 return Error(Loc, "immediate shift value out of range");
4220 Amount = Imm;
4221 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004222
4223 return false;
4224}
4225
Jim Grosbache7fbce72011-10-03 23:38:36 +00004226/// parseFPImm - A floating point immediate expression operand.
4227ARMAsmParser::OperandMatchResultTy ARMAsmParser::
4228parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004229 // Anything that can accept a floating point constant as an operand
4230 // needs to go through here, as the regular ParseExpression is
4231 // integer only.
4232 //
4233 // This routine still creates a generic Immediate operand, containing
4234 // a bitcast of the 64-bit floating point value. The various operands
4235 // that accept floats can check whether the value is valid for them
4236 // via the standard is*() predicates.
4237
Jim Grosbache7fbce72011-10-03 23:38:36 +00004238 SMLoc S = Parser.getTok().getLoc();
4239
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004240 if (Parser.getTok().isNot(AsmToken::Hash) &&
4241 Parser.getTok().isNot(AsmToken::Dollar))
Jim Grosbache7fbce72011-10-03 23:38:36 +00004242 return MatchOperand_NoMatch;
Jim Grosbach741cd732011-10-17 22:26:03 +00004243
4244 // Disambiguate the VMOV forms that can accept an FP immediate.
4245 // vmov.f32 <sreg>, #imm
4246 // vmov.f64 <dreg>, #imm
4247 // vmov.f32 <dreg>, #imm @ vector f32x2
4248 // vmov.f32 <qreg>, #imm @ vector f32x4
4249 //
4250 // There are also the NEON VMOV instructions which expect an
4251 // integer constant. Make sure we don't try to parse an FPImm
4252 // for these:
4253 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4254 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4255 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4256 TyOp->getToken() != ".f64"))
4257 return MatchOperand_NoMatch;
4258
Jim Grosbache7fbce72011-10-03 23:38:36 +00004259 Parser.Lex(); // Eat the '#'.
4260
4261 // Handle negation, as that still comes through as a separate token.
4262 bool isNegative = false;
4263 if (Parser.getTok().is(AsmToken::Minus)) {
4264 isNegative = true;
4265 Parser.Lex();
4266 }
4267 const AsmToken &Tok = Parser.getTok();
Jim Grosbach235c8d22012-01-19 02:47:30 +00004268 SMLoc Loc = Tok.getLoc();
Jim Grosbache7fbce72011-10-03 23:38:36 +00004269 if (Tok.is(AsmToken::Real)) {
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004270 APFloat RealVal(APFloat::IEEEsingle, Tok.getString());
Jim Grosbache7fbce72011-10-03 23:38:36 +00004271 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4272 // If we had a '-' in front, toggle the sign bit.
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004273 IntVal ^= (uint64_t)isNegative << 31;
Jim Grosbache7fbce72011-10-03 23:38:36 +00004274 Parser.Lex(); // Eat the token.
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004275 Operands.push_back(ARMOperand::CreateImm(
4276 MCConstantExpr::Create(IntVal, getContext()),
4277 S, Parser.getTok().getLoc()));
Jim Grosbache7fbce72011-10-03 23:38:36 +00004278 return MatchOperand_Success;
4279 }
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004280 // Also handle plain integers. Instructions which allow floating point
4281 // immediates also allow a raw encoded 8-bit value.
Jim Grosbache7fbce72011-10-03 23:38:36 +00004282 if (Tok.is(AsmToken::Integer)) {
4283 int64_t Val = Tok.getIntVal();
4284 Parser.Lex(); // Eat the token.
4285 if (Val > 255 || Val < 0) {
Jim Grosbach235c8d22012-01-19 02:47:30 +00004286 Error(Loc, "encoded floating point value out of range");
Jim Grosbache7fbce72011-10-03 23:38:36 +00004287 return MatchOperand_ParseFail;
4288 }
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004289 double RealVal = ARM_AM::getFPImmFloat(Val);
4290 Val = APFloat(APFloat::IEEEdouble, RealVal).bitcastToAPInt().getZExtValue();
4291 Operands.push_back(ARMOperand::CreateImm(
4292 MCConstantExpr::Create(Val, getContext()), S,
4293 Parser.getTok().getLoc()));
Jim Grosbache7fbce72011-10-03 23:38:36 +00004294 return MatchOperand_Success;
4295 }
4296
Jim Grosbach235c8d22012-01-19 02:47:30 +00004297 Error(Loc, "invalid floating point immediate");
Jim Grosbache7fbce72011-10-03 23:38:36 +00004298 return MatchOperand_ParseFail;
4299}
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004300
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004301/// Parse a arm instruction operand. For now this parses the operand regardless
4302/// of the mnemonic.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004303bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004304 StringRef Mnemonic) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004305 SMLoc S, E;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004306
4307 // Check if the current operand has a custom associated parser, if so, try to
4308 // custom parse the operand, or fallback to the general approach.
Jim Grosbach861e49c2011-02-12 01:34:40 +00004309 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4310 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004311 return false;
Jim Grosbach861e49c2011-02-12 01:34:40 +00004312 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4313 // there was a match, but an error occurred, in which case, just return that
4314 // the operand parsing failed.
4315 if (ResTy == MatchOperand_ParseFail)
4316 return true;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004317
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004318 switch (getLexer().getKind()) {
Bill Wendlingee7f1f92010-11-06 21:42:12 +00004319 default:
4320 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling2063b842010-11-18 23:43:05 +00004321 return true;
Jim Grosbachbb24c592011-07-13 18:49:30 +00004322 case AsmToken::Identifier: {
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004323 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling2063b842010-11-18 23:43:05 +00004324 return false;
Jim Grosbach0d6022d2011-07-26 20:41:24 +00004325 int Res = tryParseShiftRegister(Operands);
Jim Grosbachbb24c592011-07-13 18:49:30 +00004326 if (Res == 0) // success
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004327 return false;
Jim Grosbachbb24c592011-07-13 18:49:30 +00004328 else if (Res == -1) // irrecoverable error
4329 return true;
Jim Grosbach4eda1452011-12-20 22:26:38 +00004330 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach4ab23b52011-10-03 21:12:43 +00004331 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
4332 S = Parser.getTok().getLoc();
4333 Parser.Lex();
4334 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
4335 return false;
4336 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00004337
4338 // Fall though for the Identifier case that is not a register or a
4339 // special name.
Jim Grosbachbb24c592011-07-13 18:49:30 +00004340 }
Jim Grosbach4e380352011-10-26 21:14:08 +00004341 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderbyb084be92011-01-13 20:32:36 +00004342 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach5c6b6342011-11-01 22:38:31 +00004343 case AsmToken::String: // quoted label names.
Kevin Enderbyb084be92011-01-13 20:32:36 +00004344 case AsmToken::Dot: { // . as a branch target
Kevin Enderby146dcf22009-10-15 20:48:48 +00004345 // This was not a register so parse other operands that start with an
4346 // identifier (like labels) as expressions and create them as immediates.
4347 const MCExpr *IdVal;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004348 S = Parser.getTok().getLoc();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004349 if (getParser().ParseExpression(IdVal))
Bill Wendling2063b842010-11-18 23:43:05 +00004350 return true;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004351 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling2063b842010-11-18 23:43:05 +00004352 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4353 return false;
4354 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004355 case AsmToken::LBrac:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004356 return parseMemory(Operands);
Kevin Enderbya2b99102009-10-09 21:12:28 +00004357 case AsmToken::LCurly:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004358 return parseRegisterList(Operands);
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004359 case AsmToken::Dollar:
Owen Andersonf02d98d2011-08-29 17:17:09 +00004360 case AsmToken::Hash: {
Kevin Enderby3a80dac2009-10-13 23:33:38 +00004361 // #42 -> immediate.
4362 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004363 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00004364 Parser.Lex();
Owen Andersonf02d98d2011-08-29 17:17:09 +00004365 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby146dcf22009-10-15 20:48:48 +00004366 const MCExpr *ImmVal;
4367 if (getParser().ParseExpression(ImmVal))
Bill Wendling2063b842010-11-18 23:43:05 +00004368 return true;
Owen Andersonf02d98d2011-08-29 17:17:09 +00004369 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbach7f1f3bd2011-11-01 22:37:37 +00004370 if (CE) {
4371 int32_t Val = CE->getValue();
4372 if (isNegative && Val == 0)
4373 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Andersonf02d98d2011-08-29 17:17:09 +00004374 }
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004375 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling2063b842010-11-18 23:43:05 +00004376 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4377 return false;
Owen Andersonf02d98d2011-08-29 17:17:09 +00004378 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00004379 case AsmToken::Colon: {
4380 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng965b3c72011-01-13 07:58:56 +00004381 // FIXME: Check it's an expression prefix,
4382 // e.g. (FOO - :lower16:BAR) isn't legal.
4383 ARMMCExpr::VariantKind RefKind;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004384 if (parsePrefix(RefKind))
Jason W Kim1f7bc072011-01-11 23:53:41 +00004385 return true;
4386
Evan Cheng965b3c72011-01-13 07:58:56 +00004387 const MCExpr *SubExprVal;
4388 if (getParser().ParseExpression(SubExprVal))
Jason W Kim1f7bc072011-01-11 23:53:41 +00004389 return true;
4390
Evan Cheng965b3c72011-01-13 07:58:56 +00004391 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4392 getContext());
Jason W Kim1f7bc072011-01-11 23:53:41 +00004393 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng965b3c72011-01-13 07:58:56 +00004394 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim1f7bc072011-01-11 23:53:41 +00004395 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004396 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00004397 }
4398}
4399
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004400// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng965b3c72011-01-13 07:58:56 +00004401// :lower16: and :upper16:.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004402bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng965b3c72011-01-13 07:58:56 +00004403 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim1f7bc072011-01-11 23:53:41 +00004404
4405 // :lower16: and :upper16: modifiers
Jason W Kim93229972011-01-13 00:27:00 +00004406 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim1f7bc072011-01-11 23:53:41 +00004407 Parser.Lex(); // Eat ':'
4408
4409 if (getLexer().isNot(AsmToken::Identifier)) {
4410 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4411 return true;
4412 }
4413
4414 StringRef IDVal = Parser.getTok().getIdentifier();
4415 if (IDVal == "lower16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00004416 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00004417 } else if (IDVal == "upper16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00004418 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00004419 } else {
4420 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4421 return true;
4422 }
4423 Parser.Lex();
4424
4425 if (getLexer().isNot(AsmToken::Colon)) {
4426 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4427 return true;
4428 }
4429 Parser.Lex(); // Eat the last ':'
4430 return false;
4431}
4432
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004433/// \brief Given a mnemonic, split out possible predication code and carry
4434/// setting letters to form a canonical mnemonic and flags.
4435//
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004436// FIXME: Would be nice to autogen this.
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004437// FIXME: This is a bit of a maze of special cases.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004438StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00004439 unsigned &PredicationCode,
4440 bool &CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004441 unsigned &ProcessorIMod,
4442 StringRef &ITMask) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004443 PredicationCode = ARMCC::AL;
4444 CarrySetting = false;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004445 ProcessorIMod = 0;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004446
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004447 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004448 //
4449 // FIXME: Would be nice to autogen this.
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00004450 if ((Mnemonic == "movs" && isThumb()) ||
4451 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4452 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4453 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4454 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4455 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4456 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
Jim Grosbache16acac2011-12-19 19:43:50 +00004457 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" ||
4458 Mnemonic == "fmuls")
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004459 return Mnemonic;
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004460
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00004461 // First, split out any predication code. Ignore mnemonics we know aren't
4462 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbach8d114902011-07-20 18:20:31 +00004463 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach0c398b92011-07-27 21:58:11 +00004464 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach3636be32011-08-22 23:55:58 +00004465 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbachf6d5d602011-09-01 18:22:13 +00004466 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00004467 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4468 .Case("eq", ARMCC::EQ)
4469 .Case("ne", ARMCC::NE)
4470 .Case("hs", ARMCC::HS)
4471 .Case("cs", ARMCC::HS)
4472 .Case("lo", ARMCC::LO)
4473 .Case("cc", ARMCC::LO)
4474 .Case("mi", ARMCC::MI)
4475 .Case("pl", ARMCC::PL)
4476 .Case("vs", ARMCC::VS)
4477 .Case("vc", ARMCC::VC)
4478 .Case("hi", ARMCC::HI)
4479 .Case("ls", ARMCC::LS)
4480 .Case("ge", ARMCC::GE)
4481 .Case("lt", ARMCC::LT)
4482 .Case("gt", ARMCC::GT)
4483 .Case("le", ARMCC::LE)
4484 .Case("al", ARMCC::AL)
4485 .Default(~0U);
4486 if (CC != ~0U) {
4487 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4488 PredicationCode = CC;
4489 }
Bill Wendling193961b2010-10-29 23:50:21 +00004490 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004491
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004492 // Next, determine if we have a carry setting bit. We explicitly ignore all
4493 // the instructions we know end in 's'.
4494 if (Mnemonic.endswith("s") &&
Jim Grosbachd3e8e292011-08-17 22:49:09 +00004495 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00004496 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4497 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4498 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach086d0132011-12-08 00:49:29 +00004499 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach54337b82011-12-10 00:01:02 +00004500 Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
Jim Grosbach92a939a2011-12-19 19:02:41 +00004501 Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" ||
Jim Grosbach489ed592011-12-22 19:20:45 +00004502 Mnemonic == "fmuls" || Mnemonic == "fcmps" ||
Jim Grosbach51726e22011-07-29 20:26:09 +00004503 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004504 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4505 CarrySetting = true;
4506 }
4507
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004508 // The "cps" instruction can have a interrupt mode operand which is glued into
4509 // the mnemonic. Check if this is the case, split it and parse the imod op
4510 if (Mnemonic.startswith("cps")) {
4511 // Split out any imod code.
4512 unsigned IMod =
4513 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4514 .Case("ie", ARM_PROC::IE)
4515 .Case("id", ARM_PROC::ID)
4516 .Default(~0U);
4517 if (IMod != ~0U) {
4518 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4519 ProcessorIMod = IMod;
4520 }
4521 }
4522
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004523 // The "it" instruction has the condition mask on the end of the mnemonic.
4524 if (Mnemonic.startswith("it")) {
4525 ITMask = Mnemonic.slice(2, Mnemonic.size());
4526 Mnemonic = Mnemonic.slice(0, 2);
4527 }
4528
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004529 return Mnemonic;
4530}
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004531
4532/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4533/// inclusion of carry set or predication code operands.
4534//
4535// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00004536void ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004537getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00004538 bool &CanAcceptPredicationCode) {
Daniel Dunbar09264122011-01-11 19:06:29 +00004539 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4540 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00004541 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00004542 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004543 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00004544 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004545 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00004546 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004547 Mnemonic == "mla" || Mnemonic == "smlal" ||
4548 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbar09264122011-01-11 19:06:29 +00004549 CanAcceptCarrySet = true;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004550 } else
Daniel Dunbar09264122011-01-11 19:06:29 +00004551 CanAcceptCarrySet = false;
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004552
Daniel Dunbar09264122011-01-11 19:06:29 +00004553 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4554 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4555 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4556 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbach803898f2011-09-06 20:27:04 +00004557 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4558 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach25977222011-08-19 23:24:36 +00004559 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach93981412011-10-11 21:55:36 +00004560 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4561 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4562 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbachb9d4e372011-08-26 22:21:51 +00004563 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4564 !isThumb()) ||
Jim Grosbachb908b7a2011-09-10 00:15:36 +00004565 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004566 CanAcceptPredicationCode = false;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004567 } else
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004568 CanAcceptPredicationCode = true;
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004569
Jim Grosbach6c45b752011-09-16 16:39:25 +00004570 if (isThumb()) {
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004571 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbachb98ab912011-06-30 22:10:46 +00004572 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004573 CanAcceptPredicationCode = false;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004574 }
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004575}
4576
Jim Grosbach7283da92011-08-16 21:12:37 +00004577bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4578 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004579 // FIXME: This is all horribly hacky. We really need a better way to deal
4580 // with optional operands like this in the matcher table.
Jim Grosbach7283da92011-08-16 21:12:37 +00004581
4582 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4583 // another does not. Specifically, the MOVW instruction does not. So we
4584 // special case it here and remove the defaulted (non-setting) cc_out
4585 // operand if that's the instruction we're trying to match.
4586 //
4587 // We do this as post-processing of the explicit operands rather than just
4588 // conditionally adding the cc_out in the first place because we need
4589 // to check the type of the parsed immediate operand.
Owen Andersond7791b92011-09-14 22:46:14 +00004590 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbach7283da92011-08-16 21:12:37 +00004591 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4592 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4593 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4594 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00004595
4596 // Register-register 'add' for thumb does not have a cc_out operand
4597 // when there are only two register operands.
4598 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4599 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4600 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4601 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4602 return true;
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004603 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004604 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4605 // have to check the immediate range here since Thumb2 has a variant
4606 // that can handle a different range and has a cc_out operand.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004607 if (((isThumb() && Mnemonic == "add") ||
4608 (isThumbTwo() && Mnemonic == "sub")) &&
4609 Operands.size() == 6 &&
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004610 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4611 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4612 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004613 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4614 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4615 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004616 return true;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004617 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4618 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004619 // selecting via the generic "add" mnemonic, so to know that we
4620 // should remove the cc_out operand, we have to explicitly check that
4621 // it's not one of the other variants. Ugh.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004622 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4623 Operands.size() == 6 &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004624 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4625 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4626 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4627 // Nest conditions rather than one big 'if' statement for readability.
4628 //
4629 // If either register is a high reg, it's either one of the SP
4630 // variants (handled above) or a 32-bit encoding, so we just
Jim Grosbach78dcaed2012-01-21 00:07:56 +00004631 // check against T3. If the second register is the PC, this is an
4632 // alternate form of ADR, which uses encoding T4, so check for that too.
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004633 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4634 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
Jim Grosbach78dcaed2012-01-21 00:07:56 +00004635 static_cast<ARMOperand*>(Operands[4])->getReg() != ARM::PC &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004636 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4637 return false;
4638 // If both registers are low, we're in an IT block, and the immediate is
4639 // in range, we should use encoding T1 instead, which has a cc_out.
4640 if (inITBlock() &&
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004641 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004642 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4643 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4644 return false;
4645
4646 // Otherwise, we use encoding T4, which does not have a cc_out
4647 // operand.
4648 return true;
4649 }
4650
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004651 // The thumb2 multiply instruction doesn't have a CCOut register, so
4652 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4653 // use the 16-bit encoding or not.
4654 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4655 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4656 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4657 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4658 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4659 // If the registers aren't low regs, the destination reg isn't the
4660 // same as one of the source regs, or the cc_out operand is zero
4661 // outside of an IT block, we have to use the 32-bit encoding, so
4662 // remove the cc_out operand.
4663 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4664 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach6efa7b92011-11-15 19:29:45 +00004665 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004666 !inITBlock() ||
4667 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4668 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4669 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4670 static_cast<ARMOperand*>(Operands[4])->getReg())))
4671 return true;
4672
Jim Grosbachefa7e952011-11-15 19:55:16 +00004673 // Also check the 'mul' syntax variant that doesn't specify an explicit
4674 // destination register.
4675 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4676 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4677 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4678 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4679 // If the registers aren't low regs or the cc_out operand is zero
4680 // outside of an IT block, we have to use the 32-bit encoding, so
4681 // remove the cc_out operand.
4682 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4683 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4684 !inITBlock()))
4685 return true;
4686
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004687
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004688
Jim Grosbach4b701af2011-08-24 21:42:27 +00004689 // Register-register 'add/sub' for thumb does not have a cc_out operand
4690 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4691 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4692 // right, this will result in better diagnostics (which operand is off)
4693 // anyway.
4694 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4695 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004696 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4697 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4698 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4699 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00004700
Jim Grosbach7283da92011-08-16 21:12:37 +00004701 return false;
4702}
4703
Jim Grosbach12952fe2011-11-11 23:08:10 +00004704static bool isDataTypeToken(StringRef Tok) {
4705 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4706 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4707 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4708 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4709 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4710 Tok == ".f" || Tok == ".d";
4711}
4712
4713// FIXME: This bit should probably be handled via an explicit match class
4714// in the .td files that matches the suffix instead of having it be
4715// a literal string token the way it is now.
4716static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4717 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4718}
4719
Jim Grosbach8be2f652011-12-09 23:34:09 +00004720static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004721/// Parse an arm instruction mnemonic followed by its operands.
4722bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4723 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach8be2f652011-12-09 23:34:09 +00004724 // Apply mnemonic aliases before doing anything else, as the destination
4725 // mnemnonic may include suffices and we want to handle them normally.
4726 // The generic tblgen'erated code does this later, at the start of
4727 // MatchInstructionImpl(), but that's too late for aliases that include
4728 // any sort of suffix.
4729 unsigned AvailableFeatures = getAvailableFeatures();
4730 applyMnemonicAliases(Name, AvailableFeatures);
4731
Jim Grosbachab5830e2011-12-14 02:16:11 +00004732 // First check for the ARM-specific .req directive.
4733 if (Parser.getTok().is(AsmToken::Identifier) &&
4734 Parser.getTok().getIdentifier() == ".req") {
4735 parseDirectiveReq(Name, NameLoc);
4736 // We always return 'error' for this, as we're done with this
4737 // statement and don't need to match the 'instruction."
4738 return true;
4739 }
4740
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004741 // Create the leading tokens for the mnemonic, split by '.' characters.
4742 size_t Start = 0, Next = Name.find('.');
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004743 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004744
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004745 // Split out the predication code and carry setting flag from the mnemonic.
4746 unsigned PredicationCode;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004747 unsigned ProcessorIMod;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004748 bool CarrySetting;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004749 StringRef ITMask;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004750 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004751 ProcessorIMod, ITMask);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004752
Jim Grosbach1c171b12011-08-25 17:23:55 +00004753 // In Thumb1, only the branch (B) instruction can be predicated.
4754 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4755 Parser.EatToEndOfStatement();
4756 return Error(NameLoc, "conditional execution not supported in Thumb1");
4757 }
4758
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004759 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4760
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004761 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4762 // is the mask as it will be for the IT encoding if the conditional
4763 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4764 // where the conditional bit0 is zero, the instruction post-processing
4765 // will adjust the mask accordingly.
4766 if (Mnemonic == "it") {
Jim Grosbached16ec42011-08-29 22:24:09 +00004767 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4768 if (ITMask.size() > 3) {
4769 Parser.EatToEndOfStatement();
4770 return Error(Loc, "too many conditions on IT instruction");
4771 }
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004772 unsigned Mask = 8;
4773 for (unsigned i = ITMask.size(); i != 0; --i) {
4774 char pos = ITMask[i - 1];
4775 if (pos != 't' && pos != 'e') {
4776 Parser.EatToEndOfStatement();
Jim Grosbached16ec42011-08-29 22:24:09 +00004777 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004778 }
4779 Mask >>= 1;
4780 if (ITMask[i - 1] == 't')
4781 Mask |= 8;
4782 }
Jim Grosbached16ec42011-08-29 22:24:09 +00004783 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004784 }
4785
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004786 // FIXME: This is all a pretty gross hack. We should automatically handle
4787 // optional operands like this via tblgen.
Bill Wendling219dabd2010-11-21 10:56:05 +00004788
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004789 // Next, add the CCOut and ConditionCode operands, if needed.
4790 //
4791 // For mnemonics which can ever incorporate a carry setting bit or predication
4792 // code, our matching model involves us always generating CCOut and
4793 // ConditionCode operands to match the mnemonic "as written" and then we let
4794 // the matcher deal with finding the right instruction or generating an
4795 // appropriate error.
4796 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004797 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004798
Jim Grosbach03a8a162011-07-14 22:04:21 +00004799 // If we had a carry-set on an instruction that can't do that, issue an
4800 // error.
4801 if (!CanAcceptCarrySet && CarrySetting) {
4802 Parser.EatToEndOfStatement();
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004803 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach03a8a162011-07-14 22:04:21 +00004804 "' can not set flags, but 's' suffix specified");
4805 }
Jim Grosbach0a547702011-07-22 17:44:50 +00004806 // If we had a predication code on an instruction that can't do that, issue an
4807 // error.
4808 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4809 Parser.EatToEndOfStatement();
4810 return Error(NameLoc, "instruction '" + Mnemonic +
4811 "' is not predicable, but condition code specified");
4812 }
Jim Grosbach03a8a162011-07-14 22:04:21 +00004813
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004814 // Add the carry setting operand, if necessary.
Jim Grosbached16ec42011-08-29 22:24:09 +00004815 if (CanAcceptCarrySet) {
4816 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004817 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbached16ec42011-08-29 22:24:09 +00004818 Loc));
4819 }
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004820
4821 // Add the predication code operand, if necessary.
4822 if (CanAcceptPredicationCode) {
Jim Grosbached16ec42011-08-29 22:24:09 +00004823 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4824 CarrySetting);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004825 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbached16ec42011-08-29 22:24:09 +00004826 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004827 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004828
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004829 // Add the processor imod operand, if necessary.
4830 if (ProcessorIMod) {
4831 Operands.push_back(ARMOperand::CreateImm(
4832 MCConstantExpr::Create(ProcessorIMod, getContext()),
4833 NameLoc, NameLoc));
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004834 }
4835
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004836 // Add the remaining tokens in the mnemonic.
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004837 while (Next != StringRef::npos) {
4838 Start = Next;
4839 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004840 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004841
Jim Grosbach12952fe2011-11-11 23:08:10 +00004842 // Some NEON instructions have an optional datatype suffix that is
4843 // completely ignored. Check for that.
4844 if (isDataTypeToken(ExtraToken) &&
4845 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4846 continue;
4847
Jim Grosbach39c6e1d2011-09-07 16:06:04 +00004848 if (ExtraToken != ".n") {
4849 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4850 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4851 }
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004852 }
4853
4854 // Read the remaining operands.
4855 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004856 // Read the first operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004857 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnera2a9d162010-09-11 16:18:25 +00004858 Parser.EatToEndOfStatement();
4859 return true;
4860 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004861
4862 while (getLexer().is(AsmToken::Comma)) {
Sean Callanana83fd7d2010-01-19 20:27:46 +00004863 Parser.Lex(); // Eat the comma.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004864
4865 // Parse and remember the operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004866 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnera2a9d162010-09-11 16:18:25 +00004867 Parser.EatToEndOfStatement();
4868 return true;
4869 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004870 }
4871 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00004872
Chris Lattnera2a9d162010-09-11 16:18:25 +00004873 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbachb8d9f512011-10-07 18:27:04 +00004874 SMLoc Loc = getLexer().getLoc();
Chris Lattnera2a9d162010-09-11 16:18:25 +00004875 Parser.EatToEndOfStatement();
Jim Grosbachb8d9f512011-10-07 18:27:04 +00004876 return Error(Loc, "unexpected token in argument list");
Chris Lattnera2a9d162010-09-11 16:18:25 +00004877 }
Bill Wendlingee7f1f92010-11-06 21:42:12 +00004878
Chris Lattner91689c12010-09-08 05:10:46 +00004879 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004880
Jim Grosbach7283da92011-08-16 21:12:37 +00004881 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4882 // do and don't have a cc_out optional-def operand. With some spot-checks
4883 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004884 // parse and adjust accordingly before actually matching. We shouldn't ever
4885 // try to remove a cc_out operand that was explicitly set on the the
4886 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4887 // table driven matcher doesn't fit well with the ARM instruction set.
4888 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004889 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4890 Operands.erase(Operands.begin() + 1);
4891 delete Op;
4892 }
4893
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00004894 // ARM mode 'blx' need special handling, as the register operand version
4895 // is predicable, but the label operand version is not. So, we can't rely
4896 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach6e5778f2011-10-07 23:24:09 +00004897 // a k_CondCode operand in the list. If we're trying to match the label
4898 // version, remove the k_CondCode operand here.
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00004899 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4900 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4901 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4902 Operands.erase(Operands.begin() + 1);
4903 delete Op;
4904 }
Jim Grosbach8cffa282011-08-11 23:51:13 +00004905
4906 // The vector-compare-to-zero instructions have a literal token "#0" at
4907 // the end that comes to here as an immediate operand. Convert it to a
4908 // token to play nicely with the matcher.
4909 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4910 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4911 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4912 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4913 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4914 if (CE && CE->getValue() == 0) {
4915 Operands.erase(Operands.begin() + 5);
4916 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4917 delete Op;
4918 }
4919 }
Jim Grosbach46b66462011-10-03 22:30:24 +00004920 // VCMP{E} does the same thing, but with a different operand count.
4921 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4922 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4923 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4924 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4925 if (CE && CE->getValue() == 0) {
4926 Operands.erase(Operands.begin() + 4);
4927 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4928 delete Op;
4929 }
4930 }
Jim Grosbachc3c32d92011-08-22 23:47:13 +00004931 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
Jim Grosbach1f1a3592011-12-13 20:50:38 +00004932 // end. Convert it to a token here. Take care not to convert those
4933 // that should hit the Thumb2 encoding.
Jim Grosbachc3c32d92011-08-22 23:47:13 +00004934 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
Jim Grosbach1f1a3592011-12-13 20:50:38 +00004935 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4936 static_cast<ARMOperand*>(Operands[4])->isReg() &&
Jim Grosbachc3c32d92011-08-22 23:47:13 +00004937 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4938 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4939 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
Jim Grosbach1f1a3592011-12-13 20:50:38 +00004940 if (CE && CE->getValue() == 0 &&
4941 (isThumbOne() ||
Jim Grosbach5ac89672011-12-13 21:06:41 +00004942 // The cc_out operand matches the IT block.
4943 ((inITBlock() != CarrySetting) &&
4944 // Neither register operand is a high register.
Jim Grosbach1f1a3592011-12-13 20:50:38 +00004945 (isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach5ac89672011-12-13 21:06:41 +00004946 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()))))){
Jim Grosbachc3c32d92011-08-22 23:47:13 +00004947 Operands.erase(Operands.begin() + 5);
4948 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4949 delete Op;
4950 }
4951 }
4952
Chris Lattnerf29c0b62010-01-14 22:21:20 +00004953 return false;
Kevin Enderbyccab3172009-09-15 00:27:25 +00004954}
4955
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004956// Validate context-sensitive operand constraints.
Jim Grosbach169b2be2011-08-23 18:13:04 +00004957
4958// return 'true' if register list contains non-low GPR registers,
4959// 'false' otherwise. If Reg is in the register list or is HiReg, set
4960// 'containsReg' to true.
4961static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4962 unsigned HiReg, bool &containsReg) {
4963 containsReg = false;
4964 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4965 unsigned OpReg = Inst.getOperand(i).getReg();
4966 if (OpReg == Reg)
4967 containsReg = true;
4968 // Anything other than a low register isn't legal here.
4969 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4970 return true;
4971 }
4972 return false;
4973}
4974
Jim Grosbacha31f2232011-09-07 18:05:34 +00004975// Check if the specified regisgter is in the register list of the inst,
4976// starting at the indicated operand number.
4977static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4978 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4979 unsigned OpReg = Inst.getOperand(i).getReg();
4980 if (OpReg == Reg)
4981 return true;
4982 }
4983 return false;
4984}
4985
Jim Grosbached16ec42011-08-29 22:24:09 +00004986// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4987// the ARMInsts array) instead. Getting that here requires awkward
4988// API changes, though. Better way?
4989namespace llvm {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00004990extern const MCInstrDesc ARMInsts[];
Jim Grosbached16ec42011-08-29 22:24:09 +00004991}
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00004992static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbached16ec42011-08-29 22:24:09 +00004993 return ARMInsts[Opcode];
4994}
4995
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004996// FIXME: We would really like to be able to tablegen'erate this.
4997bool ARMAsmParser::
4998validateInstruction(MCInst &Inst,
4999 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00005000 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbached16ec42011-08-29 22:24:09 +00005001 SMLoc Loc = Operands[0]->getStartLoc();
5002 // Check the IT block state first.
Owen Anderson44ae2da2011-09-13 17:59:19 +00005003 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
5004 // being allowed in IT blocks, but not being predicable. It just always
5005 // executes.
5006 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbached16ec42011-08-29 22:24:09 +00005007 unsigned bit = 1;
5008 if (ITState.FirstCond)
5009 ITState.FirstCond = false;
5010 else
Jim Grosbacha0d34d32011-09-02 23:22:08 +00005011 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbached16ec42011-08-29 22:24:09 +00005012 // The instruction must be predicable.
5013 if (!MCID.isPredicable())
5014 return Error(Loc, "instructions in IT block must be predicable");
5015 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
5016 unsigned ITCond = bit ? ITState.Cond :
5017 ARMCC::getOppositeCondition(ITState.Cond);
5018 if (Cond != ITCond) {
5019 // Find the condition code Operand to get its SMLoc information.
5020 SMLoc CondLoc;
5021 for (unsigned i = 1; i < Operands.size(); ++i)
5022 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
5023 CondLoc = Operands[i]->getStartLoc();
5024 return Error(CondLoc, "incorrect condition in IT block; got '" +
5025 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
5026 "', but expected '" +
5027 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
5028 }
Jim Grosbachc61fc8f2011-08-31 18:29:05 +00005029 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00005030 } else if (isThumbTwo() && MCID.isPredicable() &&
5031 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson29cfe6c2011-09-09 21:48:23 +00005032 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
5033 Inst.getOpcode() != ARM::t2B)
Jim Grosbached16ec42011-08-29 22:24:09 +00005034 return Error(Loc, "predicated instructions must be in IT block");
5035
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005036 switch (Inst.getOpcode()) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00005037 case ARM::LDRD:
5038 case ARM::LDRD_PRE:
5039 case ARM::LDRD_POST:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005040 case ARM::LDREXD: {
5041 // Rt2 must be Rt + 1.
5042 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5043 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5044 if (Rt2 != Rt + 1)
5045 return Error(Operands[3]->getStartLoc(),
5046 "destination operands must be sequential");
5047 return false;
5048 }
Jim Grosbacheb09f492011-08-11 20:28:23 +00005049 case ARM::STRD: {
5050 // Rt2 must be Rt + 1.
5051 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5052 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5053 if (Rt2 != Rt + 1)
5054 return Error(Operands[3]->getStartLoc(),
5055 "source operands must be sequential");
5056 return false;
5057 }
Jim Grosbachf7164b22011-08-10 20:49:18 +00005058 case ARM::STRD_PRE:
5059 case ARM::STRD_POST:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005060 case ARM::STREXD: {
5061 // Rt2 must be Rt + 1.
5062 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5063 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
5064 if (Rt2 != Rt + 1)
Jim Grosbacheb09f492011-08-11 20:28:23 +00005065 return Error(Operands[3]->getStartLoc(),
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005066 "source operands must be sequential");
5067 return false;
5068 }
Jim Grosbach03f56d92011-07-27 21:09:25 +00005069 case ARM::SBFX:
5070 case ARM::UBFX: {
5071 // width must be in range [1, 32-lsb]
5072 unsigned lsb = Inst.getOperand(2).getImm();
5073 unsigned widthm1 = Inst.getOperand(3).getImm();
5074 if (widthm1 >= 32 - lsb)
5075 return Error(Operands[5]->getStartLoc(),
5076 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach64610e52011-08-16 21:42:31 +00005077 return false;
Jim Grosbach03f56d92011-07-27 21:09:25 +00005078 }
Jim Grosbach90103cc2011-08-18 21:50:53 +00005079 case ARM::tLDMIA: {
Jim Grosbacha31f2232011-09-07 18:05:34 +00005080 // If we're parsing Thumb2, the .w variant is available and handles
5081 // most cases that are normally illegal for a Thumb1 LDM
5082 // instruction. We'll make the transformation in processInstruction()
5083 // if necessary.
5084 //
Jim Grosbach90103cc2011-08-18 21:50:53 +00005085 // Thumb LDM instructions are writeback iff the base register is not
5086 // in the register list.
5087 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach139acd22011-08-22 23:01:07 +00005088 bool hasWritebackToken =
5089 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5090 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbach169b2be2011-08-23 18:13:04 +00005091 bool listContainsBase;
Jim Grosbacha31f2232011-09-07 18:05:34 +00005092 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00005093 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
5094 "registers must be in range r0-r7");
Jim Grosbach90103cc2011-08-18 21:50:53 +00005095 // If we should have writeback, then there should be a '!' token.
Jim Grosbacha31f2232011-09-07 18:05:34 +00005096 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach90103cc2011-08-18 21:50:53 +00005097 return Error(Operands[2]->getStartLoc(),
5098 "writeback operator '!' expected");
Jim Grosbacha31f2232011-09-07 18:05:34 +00005099 // If we should not have writeback, there must not be a '!'. This is
5100 // true even for the 32-bit wide encodings.
Jim Grosbach169b2be2011-08-23 18:13:04 +00005101 if (listContainsBase && hasWritebackToken)
Jim Grosbach139acd22011-08-22 23:01:07 +00005102 return Error(Operands[3]->getStartLoc(),
5103 "writeback operator '!' not allowed when base register "
5104 "in register list");
Jim Grosbach90103cc2011-08-18 21:50:53 +00005105
5106 break;
5107 }
Jim Grosbacha31f2232011-09-07 18:05:34 +00005108 case ARM::t2LDMIA_UPD: {
5109 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
5110 return Error(Operands[4]->getStartLoc(),
5111 "writeback operator '!' not allowed when base register "
5112 "in register list");
5113 break;
5114 }
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005115 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
5116 // so only issue a diagnostic for thumb1. The instructions will be
5117 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach38c59fc2011-08-22 23:17:34 +00005118 case ARM::tPOP: {
Jim Grosbach169b2be2011-08-23 18:13:04 +00005119 bool listContainsBase;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005120 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
5121 !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00005122 return Error(Operands[2]->getStartLoc(),
5123 "registers must be in range r0-r7 or pc");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00005124 break;
5125 }
5126 case ARM::tPUSH: {
Jim Grosbach169b2be2011-08-23 18:13:04 +00005127 bool listContainsBase;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005128 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
5129 !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00005130 return Error(Operands[2]->getStartLoc(),
5131 "registers must be in range r0-r7 or lr");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00005132 break;
5133 }
Jim Grosbachd80d1692011-08-23 18:15:37 +00005134 case ARM::tSTMIA_UPD: {
5135 bool listContainsBase;
Jim Grosbach099c9762011-09-16 20:50:13 +00005136 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachd80d1692011-08-23 18:15:37 +00005137 return Error(Operands[4]->getStartLoc(),
5138 "registers must be in range r0-r7");
5139 break;
5140 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005141 }
5142
5143 return false;
5144}
5145
Jim Grosbach2c590522011-12-20 20:46:29 +00005146static unsigned getRealVSTLNOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbacheb538222011-12-02 22:34:51 +00005147 switch(Opc) {
5148 default: assert(0 && "unexpected opcode!");
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005149 // VST1LN
5150 case ARM::VST1LNdWB_fixed_Asm_8: case ARM::VST1LNdWB_fixed_Asm_P8:
5151 case ARM::VST1LNdWB_fixed_Asm_I8: case ARM::VST1LNdWB_fixed_Asm_S8:
5152 case ARM::VST1LNdWB_fixed_Asm_U8:
Jim Grosbach2c590522011-12-20 20:46:29 +00005153 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005154 return ARM::VST1LNd8_UPD;
5155 case ARM::VST1LNdWB_fixed_Asm_16: case ARM::VST1LNdWB_fixed_Asm_P16:
5156 case ARM::VST1LNdWB_fixed_Asm_I16: case ARM::VST1LNdWB_fixed_Asm_S16:
5157 case ARM::VST1LNdWB_fixed_Asm_U16:
Jim Grosbach2c590522011-12-20 20:46:29 +00005158 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005159 return ARM::VST1LNd16_UPD;
5160 case ARM::VST1LNdWB_fixed_Asm_32: case ARM::VST1LNdWB_fixed_Asm_F:
5161 case ARM::VST1LNdWB_fixed_Asm_F32: case ARM::VST1LNdWB_fixed_Asm_I32:
5162 case ARM::VST1LNdWB_fixed_Asm_S32: case ARM::VST1LNdWB_fixed_Asm_U32:
Jim Grosbach2c590522011-12-20 20:46:29 +00005163 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005164 return ARM::VST1LNd32_UPD;
5165 case ARM::VST1LNdWB_register_Asm_8: case ARM::VST1LNdWB_register_Asm_P8:
5166 case ARM::VST1LNdWB_register_Asm_I8: case ARM::VST1LNdWB_register_Asm_S8:
5167 case ARM::VST1LNdWB_register_Asm_U8:
Jim Grosbach2c590522011-12-20 20:46:29 +00005168 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005169 return ARM::VST1LNd8_UPD;
5170 case ARM::VST1LNdWB_register_Asm_16: case ARM::VST1LNdWB_register_Asm_P16:
5171 case ARM::VST1LNdWB_register_Asm_I16: case ARM::VST1LNdWB_register_Asm_S16:
5172 case ARM::VST1LNdWB_register_Asm_U16:
Jim Grosbach2c590522011-12-20 20:46:29 +00005173 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005174 return ARM::VST1LNd16_UPD;
5175 case ARM::VST1LNdWB_register_Asm_32: case ARM::VST1LNdWB_register_Asm_F:
5176 case ARM::VST1LNdWB_register_Asm_F32: case ARM::VST1LNdWB_register_Asm_I32:
5177 case ARM::VST1LNdWB_register_Asm_S32: case ARM::VST1LNdWB_register_Asm_U32:
Jim Grosbach2c590522011-12-20 20:46:29 +00005178 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005179 return ARM::VST1LNd32_UPD;
5180 case ARM::VST1LNdAsm_8: case ARM::VST1LNdAsm_P8:
5181 case ARM::VST1LNdAsm_I8: case ARM::VST1LNdAsm_S8:
5182 case ARM::VST1LNdAsm_U8:
Jim Grosbach2c590522011-12-20 20:46:29 +00005183 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005184 return ARM::VST1LNd8;
5185 case ARM::VST1LNdAsm_16: case ARM::VST1LNdAsm_P16:
5186 case ARM::VST1LNdAsm_I16: case ARM::VST1LNdAsm_S16:
5187 case ARM::VST1LNdAsm_U16:
Jim Grosbach2c590522011-12-20 20:46:29 +00005188 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005189 return ARM::VST1LNd16;
5190 case ARM::VST1LNdAsm_32: case ARM::VST1LNdAsm_F:
5191 case ARM::VST1LNdAsm_F32: case ARM::VST1LNdAsm_I32:
5192 case ARM::VST1LNdAsm_S32: case ARM::VST1LNdAsm_U32:
Jim Grosbach2c590522011-12-20 20:46:29 +00005193 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005194 return ARM::VST1LNd32;
5195
5196 // VST2LN
5197 case ARM::VST2LNdWB_fixed_Asm_8: case ARM::VST2LNdWB_fixed_Asm_P8:
5198 case ARM::VST2LNdWB_fixed_Asm_I8: case ARM::VST2LNdWB_fixed_Asm_S8:
5199 case ARM::VST2LNdWB_fixed_Asm_U8:
Jim Grosbach2c590522011-12-20 20:46:29 +00005200 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005201 return ARM::VST2LNd8_UPD;
5202 case ARM::VST2LNdWB_fixed_Asm_16: case ARM::VST2LNdWB_fixed_Asm_P16:
5203 case ARM::VST2LNdWB_fixed_Asm_I16: case ARM::VST2LNdWB_fixed_Asm_S16:
5204 case ARM::VST2LNdWB_fixed_Asm_U16:
Jim Grosbach2c590522011-12-20 20:46:29 +00005205 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005206 return ARM::VST2LNd16_UPD;
5207 case ARM::VST2LNdWB_fixed_Asm_32: case ARM::VST2LNdWB_fixed_Asm_F:
5208 case ARM::VST2LNdWB_fixed_Asm_F32: case ARM::VST2LNdWB_fixed_Asm_I32:
5209 case ARM::VST2LNdWB_fixed_Asm_S32: case ARM::VST2LNdWB_fixed_Asm_U32:
Jim Grosbach2c590522011-12-20 20:46:29 +00005210 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005211 return ARM::VST2LNd32_UPD;
Jim Grosbach2c590522011-12-20 20:46:29 +00005212 case ARM::VST2LNqWB_fixed_Asm_16: case ARM::VST2LNqWB_fixed_Asm_P16:
5213 case ARM::VST2LNqWB_fixed_Asm_I16: case ARM::VST2LNqWB_fixed_Asm_S16:
5214 case ARM::VST2LNqWB_fixed_Asm_U16:
5215 Spacing = 2;
5216 return ARM::VST2LNq16_UPD;
5217 case ARM::VST2LNqWB_fixed_Asm_32: case ARM::VST2LNqWB_fixed_Asm_F:
5218 case ARM::VST2LNqWB_fixed_Asm_F32: case ARM::VST2LNqWB_fixed_Asm_I32:
5219 case ARM::VST2LNqWB_fixed_Asm_S32: case ARM::VST2LNqWB_fixed_Asm_U32:
5220 Spacing = 2;
5221 return ARM::VST2LNq32_UPD;
5222
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005223 case ARM::VST2LNdWB_register_Asm_8: case ARM::VST2LNdWB_register_Asm_P8:
5224 case ARM::VST2LNdWB_register_Asm_I8: case ARM::VST2LNdWB_register_Asm_S8:
5225 case ARM::VST2LNdWB_register_Asm_U8:
Jim Grosbach2c590522011-12-20 20:46:29 +00005226 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005227 return ARM::VST2LNd8_UPD;
5228 case ARM::VST2LNdWB_register_Asm_16: case ARM::VST2LNdWB_register_Asm_P16:
5229 case ARM::VST2LNdWB_register_Asm_I16: case ARM::VST2LNdWB_register_Asm_S16:
5230 case ARM::VST2LNdWB_register_Asm_U16:
Jim Grosbach2c590522011-12-20 20:46:29 +00005231 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005232 return ARM::VST2LNd16_UPD;
5233 case ARM::VST2LNdWB_register_Asm_32: case ARM::VST2LNdWB_register_Asm_F:
5234 case ARM::VST2LNdWB_register_Asm_F32: case ARM::VST2LNdWB_register_Asm_I32:
5235 case ARM::VST2LNdWB_register_Asm_S32: case ARM::VST2LNdWB_register_Asm_U32:
Jim Grosbach2c590522011-12-20 20:46:29 +00005236 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005237 return ARM::VST2LNd32_UPD;
Jim Grosbach2c590522011-12-20 20:46:29 +00005238 case ARM::VST2LNqWB_register_Asm_16: case ARM::VST2LNqWB_register_Asm_P16:
5239 case ARM::VST2LNqWB_register_Asm_I16: case ARM::VST2LNqWB_register_Asm_S16:
5240 case ARM::VST2LNqWB_register_Asm_U16:
5241 Spacing = 2;
5242 return ARM::VST2LNq16_UPD;
5243 case ARM::VST2LNqWB_register_Asm_32: case ARM::VST2LNqWB_register_Asm_F:
5244 case ARM::VST2LNqWB_register_Asm_F32: case ARM::VST2LNqWB_register_Asm_I32:
5245 case ARM::VST2LNqWB_register_Asm_S32: case ARM::VST2LNqWB_register_Asm_U32:
5246 Spacing = 2;
5247 return ARM::VST2LNq32_UPD;
5248
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005249 case ARM::VST2LNdAsm_8: case ARM::VST2LNdAsm_P8:
5250 case ARM::VST2LNdAsm_I8: case ARM::VST2LNdAsm_S8:
5251 case ARM::VST2LNdAsm_U8:
Jim Grosbach2c590522011-12-20 20:46:29 +00005252 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005253 return ARM::VST2LNd8;
5254 case ARM::VST2LNdAsm_16: case ARM::VST2LNdAsm_P16:
5255 case ARM::VST2LNdAsm_I16: case ARM::VST2LNdAsm_S16:
5256 case ARM::VST2LNdAsm_U16:
Jim Grosbach2c590522011-12-20 20:46:29 +00005257 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005258 return ARM::VST2LNd16;
5259 case ARM::VST2LNdAsm_32: case ARM::VST2LNdAsm_F:
5260 case ARM::VST2LNdAsm_F32: case ARM::VST2LNdAsm_I32:
5261 case ARM::VST2LNdAsm_S32: case ARM::VST2LNdAsm_U32:
Jim Grosbach2c590522011-12-20 20:46:29 +00005262 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005263 return ARM::VST2LNd32;
Jim Grosbach2c590522011-12-20 20:46:29 +00005264 case ARM::VST2LNqAsm_16: case ARM::VST2LNqAsm_P16:
5265 case ARM::VST2LNqAsm_I16: case ARM::VST2LNqAsm_S16:
5266 case ARM::VST2LNqAsm_U16:
5267 Spacing = 2;
5268 return ARM::VST2LNq16;
5269 case ARM::VST2LNqAsm_32: case ARM::VST2LNqAsm_F:
5270 case ARM::VST2LNqAsm_F32: case ARM::VST2LNqAsm_I32:
5271 case ARM::VST2LNqAsm_S32: case ARM::VST2LNqAsm_U32:
5272 Spacing = 2;
5273 return ARM::VST2LNq32;
Jim Grosbacheb538222011-12-02 22:34:51 +00005274 }
5275}
5276
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005277static unsigned getRealVLDLNOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach04945c42011-12-02 00:35:16 +00005278 switch(Opc) {
5279 default: assert(0 && "unexpected opcode!");
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005280 // VLD1LN
5281 case ARM::VLD1LNdWB_fixed_Asm_8: case ARM::VLD1LNdWB_fixed_Asm_P8:
5282 case ARM::VLD1LNdWB_fixed_Asm_I8: case ARM::VLD1LNdWB_fixed_Asm_S8:
5283 case ARM::VLD1LNdWB_fixed_Asm_U8:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005284 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005285 return ARM::VLD1LNd8_UPD;
5286 case ARM::VLD1LNdWB_fixed_Asm_16: case ARM::VLD1LNdWB_fixed_Asm_P16:
5287 case ARM::VLD1LNdWB_fixed_Asm_I16: case ARM::VLD1LNdWB_fixed_Asm_S16:
5288 case ARM::VLD1LNdWB_fixed_Asm_U16:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005289 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005290 return ARM::VLD1LNd16_UPD;
5291 case ARM::VLD1LNdWB_fixed_Asm_32: case ARM::VLD1LNdWB_fixed_Asm_F:
5292 case ARM::VLD1LNdWB_fixed_Asm_F32: case ARM::VLD1LNdWB_fixed_Asm_I32:
5293 case ARM::VLD1LNdWB_fixed_Asm_S32: case ARM::VLD1LNdWB_fixed_Asm_U32:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005294 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005295 return ARM::VLD1LNd32_UPD;
5296 case ARM::VLD1LNdWB_register_Asm_8: case ARM::VLD1LNdWB_register_Asm_P8:
5297 case ARM::VLD1LNdWB_register_Asm_I8: case ARM::VLD1LNdWB_register_Asm_S8:
5298 case ARM::VLD1LNdWB_register_Asm_U8:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005299 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005300 return ARM::VLD1LNd8_UPD;
5301 case ARM::VLD1LNdWB_register_Asm_16: case ARM::VLD1LNdWB_register_Asm_P16:
5302 case ARM::VLD1LNdWB_register_Asm_I16: case ARM::VLD1LNdWB_register_Asm_S16:
5303 case ARM::VLD1LNdWB_register_Asm_U16:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005304 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005305 return ARM::VLD1LNd16_UPD;
5306 case ARM::VLD1LNdWB_register_Asm_32: case ARM::VLD1LNdWB_register_Asm_F:
5307 case ARM::VLD1LNdWB_register_Asm_F32: case ARM::VLD1LNdWB_register_Asm_I32:
5308 case ARM::VLD1LNdWB_register_Asm_S32: case ARM::VLD1LNdWB_register_Asm_U32:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005309 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005310 return ARM::VLD1LNd32_UPD;
5311 case ARM::VLD1LNdAsm_8: case ARM::VLD1LNdAsm_P8:
5312 case ARM::VLD1LNdAsm_I8: case ARM::VLD1LNdAsm_S8:
5313 case ARM::VLD1LNdAsm_U8:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005314 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005315 return ARM::VLD1LNd8;
5316 case ARM::VLD1LNdAsm_16: case ARM::VLD1LNdAsm_P16:
5317 case ARM::VLD1LNdAsm_I16: case ARM::VLD1LNdAsm_S16:
5318 case ARM::VLD1LNdAsm_U16:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005319 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005320 return ARM::VLD1LNd16;
5321 case ARM::VLD1LNdAsm_32: case ARM::VLD1LNdAsm_F:
5322 case ARM::VLD1LNdAsm_F32: case ARM::VLD1LNdAsm_I32:
5323 case ARM::VLD1LNdAsm_S32: case ARM::VLD1LNdAsm_U32:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005324 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005325 return ARM::VLD1LNd32;
5326
5327 // VLD2LN
5328 case ARM::VLD2LNdWB_fixed_Asm_8: case ARM::VLD2LNdWB_fixed_Asm_P8:
5329 case ARM::VLD2LNdWB_fixed_Asm_I8: case ARM::VLD2LNdWB_fixed_Asm_S8:
5330 case ARM::VLD2LNdWB_fixed_Asm_U8:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005331 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005332 return ARM::VLD2LNd8_UPD;
5333 case ARM::VLD2LNdWB_fixed_Asm_16: case ARM::VLD2LNdWB_fixed_Asm_P16:
5334 case ARM::VLD2LNdWB_fixed_Asm_I16: case ARM::VLD2LNdWB_fixed_Asm_S16:
5335 case ARM::VLD2LNdWB_fixed_Asm_U16:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005336 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005337 return ARM::VLD2LNd16_UPD;
5338 case ARM::VLD2LNdWB_fixed_Asm_32: case ARM::VLD2LNdWB_fixed_Asm_F:
5339 case ARM::VLD2LNdWB_fixed_Asm_F32: case ARM::VLD2LNdWB_fixed_Asm_I32:
5340 case ARM::VLD2LNdWB_fixed_Asm_S32: case ARM::VLD2LNdWB_fixed_Asm_U32:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005341 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005342 return ARM::VLD2LNd32_UPD;
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005343 case ARM::VLD2LNqWB_fixed_Asm_16: case ARM::VLD2LNqWB_fixed_Asm_P16:
5344 case ARM::VLD2LNqWB_fixed_Asm_I16: case ARM::VLD2LNqWB_fixed_Asm_S16:
5345 case ARM::VLD2LNqWB_fixed_Asm_U16:
5346 Spacing = 1;
5347 return ARM::VLD2LNq16_UPD;
5348 case ARM::VLD2LNqWB_fixed_Asm_32: case ARM::VLD2LNqWB_fixed_Asm_F:
5349 case ARM::VLD2LNqWB_fixed_Asm_F32: case ARM::VLD2LNqWB_fixed_Asm_I32:
5350 case ARM::VLD2LNqWB_fixed_Asm_S32: case ARM::VLD2LNqWB_fixed_Asm_U32:
5351 Spacing = 2;
5352 return ARM::VLD2LNq32_UPD;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005353 case ARM::VLD2LNdWB_register_Asm_8: case ARM::VLD2LNdWB_register_Asm_P8:
5354 case ARM::VLD2LNdWB_register_Asm_I8: case ARM::VLD2LNdWB_register_Asm_S8:
5355 case ARM::VLD2LNdWB_register_Asm_U8:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005356 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005357 return ARM::VLD2LNd8_UPD;
5358 case ARM::VLD2LNdWB_register_Asm_16: case ARM::VLD2LNdWB_register_Asm_P16:
5359 case ARM::VLD2LNdWB_register_Asm_I16: case ARM::VLD2LNdWB_register_Asm_S16:
5360 case ARM::VLD2LNdWB_register_Asm_U16:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005361 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005362 return ARM::VLD2LNd16_UPD;
5363 case ARM::VLD2LNdWB_register_Asm_32: case ARM::VLD2LNdWB_register_Asm_F:
5364 case ARM::VLD2LNdWB_register_Asm_F32: case ARM::VLD2LNdWB_register_Asm_I32:
5365 case ARM::VLD2LNdWB_register_Asm_S32: case ARM::VLD2LNdWB_register_Asm_U32:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005366 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005367 return ARM::VLD2LNd32_UPD;
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005368 case ARM::VLD2LNqWB_register_Asm_16: case ARM::VLD2LNqWB_register_Asm_P16:
5369 case ARM::VLD2LNqWB_register_Asm_I16: case ARM::VLD2LNqWB_register_Asm_S16:
5370 case ARM::VLD2LNqWB_register_Asm_U16:
5371 Spacing = 2;
5372 return ARM::VLD2LNq16_UPD;
5373 case ARM::VLD2LNqWB_register_Asm_32: case ARM::VLD2LNqWB_register_Asm_F:
5374 case ARM::VLD2LNqWB_register_Asm_F32: case ARM::VLD2LNqWB_register_Asm_I32:
5375 case ARM::VLD2LNqWB_register_Asm_S32: case ARM::VLD2LNqWB_register_Asm_U32:
5376 Spacing = 2;
5377 return ARM::VLD2LNq32_UPD;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005378 case ARM::VLD2LNdAsm_8: case ARM::VLD2LNdAsm_P8:
5379 case ARM::VLD2LNdAsm_I8: case ARM::VLD2LNdAsm_S8:
5380 case ARM::VLD2LNdAsm_U8:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005381 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005382 return ARM::VLD2LNd8;
5383 case ARM::VLD2LNdAsm_16: case ARM::VLD2LNdAsm_P16:
5384 case ARM::VLD2LNdAsm_I16: case ARM::VLD2LNdAsm_S16:
5385 case ARM::VLD2LNdAsm_U16:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005386 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005387 return ARM::VLD2LNd16;
5388 case ARM::VLD2LNdAsm_32: case ARM::VLD2LNdAsm_F:
5389 case ARM::VLD2LNdAsm_F32: case ARM::VLD2LNdAsm_I32:
5390 case ARM::VLD2LNdAsm_S32: case ARM::VLD2LNdAsm_U32:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005391 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005392 return ARM::VLD2LNd32;
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005393 case ARM::VLD2LNqAsm_16: case ARM::VLD2LNqAsm_P16:
5394 case ARM::VLD2LNqAsm_I16: case ARM::VLD2LNqAsm_S16:
5395 case ARM::VLD2LNqAsm_U16:
5396 Spacing = 2;
5397 return ARM::VLD2LNq16;
5398 case ARM::VLD2LNqAsm_32: case ARM::VLD2LNqAsm_F:
5399 case ARM::VLD2LNqAsm_F32: case ARM::VLD2LNqAsm_I32:
5400 case ARM::VLD2LNqAsm_S32: case ARM::VLD2LNqAsm_U32:
5401 Spacing = 2;
5402 return ARM::VLD2LNq32;
Jim Grosbach04945c42011-12-02 00:35:16 +00005403 }
5404}
5405
Jim Grosbachafad0532011-11-10 23:42:14 +00005406bool ARMAsmParser::
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005407processInstruction(MCInst &Inst,
5408 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5409 switch (Inst.getOpcode()) {
Jim Grosbach94298a92012-01-18 22:46:46 +00005410 // Aliases for alternate PC+imm syntax of LDR instructions.
5411 case ARM::t2LDRpcrel:
5412 Inst.setOpcode(ARM::t2LDRpci);
5413 return true;
5414 case ARM::t2LDRBpcrel:
5415 Inst.setOpcode(ARM::t2LDRBpci);
5416 return true;
5417 case ARM::t2LDRHpcrel:
5418 Inst.setOpcode(ARM::t2LDRHpci);
5419 return true;
5420 case ARM::t2LDRSBpcrel:
5421 Inst.setOpcode(ARM::t2LDRSBpci);
5422 return true;
5423 case ARM::t2LDRSHpcrel:
5424 Inst.setOpcode(ARM::t2LDRSHpci);
5425 return true;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005426 // Handle NEON VST complex aliases.
5427 case ARM::VST1LNdWB_register_Asm_8: case ARM::VST1LNdWB_register_Asm_P8:
5428 case ARM::VST1LNdWB_register_Asm_I8: case ARM::VST1LNdWB_register_Asm_S8:
5429 case ARM::VST1LNdWB_register_Asm_U8: case ARM::VST1LNdWB_register_Asm_16:
5430 case ARM::VST1LNdWB_register_Asm_P16: case ARM::VST1LNdWB_register_Asm_I16:
5431 case ARM::VST1LNdWB_register_Asm_S16: case ARM::VST1LNdWB_register_Asm_U16:
5432 case ARM::VST1LNdWB_register_Asm_32: case ARM::VST1LNdWB_register_Asm_F:
5433 case ARM::VST1LNdWB_register_Asm_F32: case ARM::VST1LNdWB_register_Asm_I32:
5434 case ARM::VST1LNdWB_register_Asm_S32: case ARM::VST1LNdWB_register_Asm_U32: {
Jim Grosbacheb538222011-12-02 22:34:51 +00005435 MCInst TmpInst;
5436 // Shuffle the operands around so the lane index operand is in the
5437 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005438 unsigned Spacing;
5439 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacheb538222011-12-02 22:34:51 +00005440 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5441 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5442 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5443 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5444 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5445 TmpInst.addOperand(Inst.getOperand(1)); // lane
5446 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5447 TmpInst.addOperand(Inst.getOperand(6));
5448 Inst = TmpInst;
5449 return true;
5450 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005451
Jim Grosbach2c590522011-12-20 20:46:29 +00005452 case ARM::VST2LNdWB_register_Asm_8: case ARM::VST2LNdWB_register_Asm_P8:
5453 case ARM::VST2LNdWB_register_Asm_I8: case ARM::VST2LNdWB_register_Asm_S8:
5454 case ARM::VST2LNdWB_register_Asm_U8: case ARM::VST2LNdWB_register_Asm_16:
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005455 case ARM::VST2LNdWB_register_Asm_P16: case ARM::VST2LNdWB_register_Asm_I16:
5456 case ARM::VST2LNdWB_register_Asm_S16: case ARM::VST2LNdWB_register_Asm_U16:
Jim Grosbach2c590522011-12-20 20:46:29 +00005457 case ARM::VST2LNdWB_register_Asm_32: case ARM::VST2LNdWB_register_Asm_F:
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005458 case ARM::VST2LNdWB_register_Asm_F32: case ARM::VST2LNdWB_register_Asm_I32:
Jim Grosbach2c590522011-12-20 20:46:29 +00005459 case ARM::VST2LNdWB_register_Asm_S32: case ARM::VST2LNdWB_register_Asm_U32:
5460 case ARM::VST2LNqWB_register_Asm_16: case ARM::VST2LNqWB_register_Asm_P16:
5461 case ARM::VST2LNqWB_register_Asm_I16: case ARM::VST2LNqWB_register_Asm_S16:
5462 case ARM::VST2LNqWB_register_Asm_U16: case ARM::VST2LNqWB_register_Asm_32:
5463 case ARM::VST2LNqWB_register_Asm_F: case ARM::VST2LNqWB_register_Asm_F32:
5464 case ARM::VST2LNqWB_register_Asm_I32: case ARM::VST2LNqWB_register_Asm_S32:
5465 case ARM::VST2LNqWB_register_Asm_U32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005466 MCInst TmpInst;
5467 // Shuffle the operands around so the lane index operand is in the
5468 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005469 unsigned Spacing;
5470 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005471 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5472 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5473 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5474 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5475 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach2c590522011-12-20 20:46:29 +00005476 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5477 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005478 TmpInst.addOperand(Inst.getOperand(1)); // lane
5479 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5480 TmpInst.addOperand(Inst.getOperand(6));
5481 Inst = TmpInst;
5482 return true;
5483 }
5484 case ARM::VST1LNdWB_fixed_Asm_8: case ARM::VST1LNdWB_fixed_Asm_P8:
5485 case ARM::VST1LNdWB_fixed_Asm_I8: case ARM::VST1LNdWB_fixed_Asm_S8:
5486 case ARM::VST1LNdWB_fixed_Asm_U8: case ARM::VST1LNdWB_fixed_Asm_16:
5487 case ARM::VST1LNdWB_fixed_Asm_P16: case ARM::VST1LNdWB_fixed_Asm_I16:
5488 case ARM::VST1LNdWB_fixed_Asm_S16: case ARM::VST1LNdWB_fixed_Asm_U16:
5489 case ARM::VST1LNdWB_fixed_Asm_32: case ARM::VST1LNdWB_fixed_Asm_F:
5490 case ARM::VST1LNdWB_fixed_Asm_F32: case ARM::VST1LNdWB_fixed_Asm_I32:
5491 case ARM::VST1LNdWB_fixed_Asm_S32: case ARM::VST1LNdWB_fixed_Asm_U32: {
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_wb
5498 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5499 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5500 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5501 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5502 TmpInst.addOperand(Inst.getOperand(1)); // lane
5503 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5504 TmpInst.addOperand(Inst.getOperand(5));
5505 Inst = TmpInst;
5506 return true;
5507 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005508
Jim Grosbach2c590522011-12-20 20:46:29 +00005509 case ARM::VST2LNdWB_fixed_Asm_8: case ARM::VST2LNdWB_fixed_Asm_P8:
5510 case ARM::VST2LNdWB_fixed_Asm_I8: case ARM::VST2LNdWB_fixed_Asm_S8:
5511 case ARM::VST2LNdWB_fixed_Asm_U8: case ARM::VST2LNdWB_fixed_Asm_16:
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005512 case ARM::VST2LNdWB_fixed_Asm_P16: case ARM::VST2LNdWB_fixed_Asm_I16:
5513 case ARM::VST2LNdWB_fixed_Asm_S16: case ARM::VST2LNdWB_fixed_Asm_U16:
Jim Grosbach2c590522011-12-20 20:46:29 +00005514 case ARM::VST2LNdWB_fixed_Asm_32: case ARM::VST2LNdWB_fixed_Asm_F:
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005515 case ARM::VST2LNdWB_fixed_Asm_F32: case ARM::VST2LNdWB_fixed_Asm_I32:
Jim Grosbach2c590522011-12-20 20:46:29 +00005516 case ARM::VST2LNdWB_fixed_Asm_S32: case ARM::VST2LNdWB_fixed_Asm_U32:
5517 case ARM::VST2LNqWB_fixed_Asm_16: case ARM::VST2LNqWB_fixed_Asm_P16:
5518 case ARM::VST2LNqWB_fixed_Asm_I16: case ARM::VST2LNqWB_fixed_Asm_S16:
5519 case ARM::VST2LNqWB_fixed_Asm_U16: case ARM::VST2LNqWB_fixed_Asm_32:
5520 case ARM::VST2LNqWB_fixed_Asm_F: case ARM::VST2LNqWB_fixed_Asm_F32:
5521 case ARM::VST2LNqWB_fixed_Asm_I32: case ARM::VST2LNqWB_fixed_Asm_S32:
5522 case ARM::VST2LNqWB_fixed_Asm_U32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005523 MCInst TmpInst;
5524 // Shuffle the operands around so the lane index operand is in the
5525 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005526 unsigned Spacing;
5527 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005528 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5529 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5530 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5531 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5532 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach2c590522011-12-20 20:46:29 +00005533 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5534 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005535 TmpInst.addOperand(Inst.getOperand(1)); // lane
5536 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5537 TmpInst.addOperand(Inst.getOperand(5));
5538 Inst = TmpInst;
5539 return true;
5540 }
5541 case ARM::VST1LNdAsm_8: case ARM::VST1LNdAsm_P8: case ARM::VST1LNdAsm_I8:
5542 case ARM::VST1LNdAsm_S8: case ARM::VST1LNdAsm_U8: case ARM::VST1LNdAsm_16:
5543 case ARM::VST1LNdAsm_P16: case ARM::VST1LNdAsm_I16: case ARM::VST1LNdAsm_S16:
5544 case ARM::VST1LNdAsm_U16: case ARM::VST1LNdAsm_32: case ARM::VST1LNdAsm_F:
5545 case ARM::VST1LNdAsm_F32: case ARM::VST1LNdAsm_I32: case ARM::VST1LNdAsm_S32:
Jim Grosbacheb538222011-12-02 22:34:51 +00005546 case ARM::VST1LNdAsm_U32: {
5547 MCInst TmpInst;
5548 // Shuffle the operands around so the lane index operand is in the
5549 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005550 unsigned Spacing;
5551 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacheb538222011-12-02 22:34:51 +00005552 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5553 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5554 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5555 TmpInst.addOperand(Inst.getOperand(1)); // lane
5556 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5557 TmpInst.addOperand(Inst.getOperand(5));
5558 Inst = TmpInst;
5559 return true;
5560 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005561
Jim Grosbach2c590522011-12-20 20:46:29 +00005562 case ARM::VST2LNdAsm_8: case ARM::VST2LNdAsm_P8: case ARM::VST2LNdAsm_I8:
5563 case ARM::VST2LNdAsm_S8: case ARM::VST2LNdAsm_U8: case ARM::VST2LNdAsm_16:
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005564 case ARM::VST2LNdAsm_P16: case ARM::VST2LNdAsm_I16: case ARM::VST2LNdAsm_S16:
Jim Grosbach2c590522011-12-20 20:46:29 +00005565 case ARM::VST2LNdAsm_U16: case ARM::VST2LNdAsm_32: case ARM::VST2LNdAsm_F:
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005566 case ARM::VST2LNdAsm_F32: case ARM::VST2LNdAsm_I32: case ARM::VST2LNdAsm_S32:
Jim Grosbach2c590522011-12-20 20:46:29 +00005567 case ARM::VST2LNdAsm_U32: case ARM::VST2LNqAsm_16: case ARM::VST2LNqAsm_P16:
5568 case ARM::VST2LNqAsm_I16: case ARM::VST2LNqAsm_S16: case ARM::VST2LNqAsm_U16:
5569 case ARM::VST2LNqAsm_32: case ARM::VST2LNqAsm_F: case ARM::VST2LNqAsm_F32:
5570 case ARM::VST2LNqAsm_I32: case ARM::VST2LNqAsm_S32: case ARM::VST2LNqAsm_U32:{
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005571 MCInst TmpInst;
5572 // Shuffle the operands around so the lane index operand is in the
5573 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005574 unsigned Spacing;
5575 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005576 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5577 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5578 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach2c590522011-12-20 20:46:29 +00005579 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5580 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005581 TmpInst.addOperand(Inst.getOperand(1)); // lane
5582 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5583 TmpInst.addOperand(Inst.getOperand(5));
5584 Inst = TmpInst;
5585 return true;
5586 }
5587 // Handle NEON VLD complex aliases.
5588 case ARM::VLD1LNdWB_register_Asm_8: case ARM::VLD1LNdWB_register_Asm_P8:
5589 case ARM::VLD1LNdWB_register_Asm_I8: case ARM::VLD1LNdWB_register_Asm_S8:
5590 case ARM::VLD1LNdWB_register_Asm_U8: case ARM::VLD1LNdWB_register_Asm_16:
5591 case ARM::VLD1LNdWB_register_Asm_P16: case ARM::VLD1LNdWB_register_Asm_I16:
5592 case ARM::VLD1LNdWB_register_Asm_S16: case ARM::VLD1LNdWB_register_Asm_U16:
5593 case ARM::VLD1LNdWB_register_Asm_32: case ARM::VLD1LNdWB_register_Asm_F:
5594 case ARM::VLD1LNdWB_register_Asm_F32: case ARM::VLD1LNdWB_register_Asm_I32:
5595 case ARM::VLD1LNdWB_register_Asm_S32: case ARM::VLD1LNdWB_register_Asm_U32: {
Jim Grosbachdda976b2011-12-02 22:01:52 +00005596 MCInst TmpInst;
5597 // Shuffle the operands around so the lane index operand is in the
5598 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005599 unsigned Spacing;
5600 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachdda976b2011-12-02 22:01:52 +00005601 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5602 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5603 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5604 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5605 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5606 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5607 TmpInst.addOperand(Inst.getOperand(1)); // lane
5608 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5609 TmpInst.addOperand(Inst.getOperand(6));
5610 Inst = TmpInst;
5611 return true;
5612 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005613
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005614 case ARM::VLD2LNdWB_register_Asm_8: case ARM::VLD2LNdWB_register_Asm_P8:
5615 case ARM::VLD2LNdWB_register_Asm_I8: case ARM::VLD2LNdWB_register_Asm_S8:
5616 case ARM::VLD2LNdWB_register_Asm_U8: case ARM::VLD2LNdWB_register_Asm_16:
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005617 case ARM::VLD2LNdWB_register_Asm_P16: case ARM::VLD2LNdWB_register_Asm_I16:
5618 case ARM::VLD2LNdWB_register_Asm_S16: case ARM::VLD2LNdWB_register_Asm_U16:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005619 case ARM::VLD2LNdWB_register_Asm_32: case ARM::VLD2LNdWB_register_Asm_F:
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005620 case ARM::VLD2LNdWB_register_Asm_F32: case ARM::VLD2LNdWB_register_Asm_I32:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005621 case ARM::VLD2LNdWB_register_Asm_S32: case ARM::VLD2LNdWB_register_Asm_U32:
Jim Grosbach2c590522011-12-20 20:46:29 +00005622 case ARM::VLD2LNqWB_register_Asm_16: case ARM::VLD2LNqWB_register_Asm_P16:
5623 case ARM::VLD2LNqWB_register_Asm_I16: case ARM::VLD2LNqWB_register_Asm_S16:
5624 case ARM::VLD2LNqWB_register_Asm_U16: case ARM::VLD2LNqWB_register_Asm_32:
5625 case ARM::VLD2LNqWB_register_Asm_F: case ARM::VLD2LNqWB_register_Asm_F32:
5626 case ARM::VLD2LNqWB_register_Asm_I32: case ARM::VLD2LNqWB_register_Asm_S32:
5627 case ARM::VLD2LNqWB_register_Asm_U32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005628 MCInst TmpInst;
5629 // Shuffle the operands around so the lane index operand is in the
5630 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005631 unsigned Spacing;
5632 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005633 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005634 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5635 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005636 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5637 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5638 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5639 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5640 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005641 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5642 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005643 TmpInst.addOperand(Inst.getOperand(1)); // lane
5644 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5645 TmpInst.addOperand(Inst.getOperand(6));
5646 Inst = TmpInst;
5647 return true;
5648 }
5649
5650 case ARM::VLD1LNdWB_fixed_Asm_8: case ARM::VLD1LNdWB_fixed_Asm_P8:
5651 case ARM::VLD1LNdWB_fixed_Asm_I8: case ARM::VLD1LNdWB_fixed_Asm_S8:
5652 case ARM::VLD1LNdWB_fixed_Asm_U8: case ARM::VLD1LNdWB_fixed_Asm_16:
5653 case ARM::VLD1LNdWB_fixed_Asm_P16: case ARM::VLD1LNdWB_fixed_Asm_I16:
5654 case ARM::VLD1LNdWB_fixed_Asm_S16: case ARM::VLD1LNdWB_fixed_Asm_U16:
5655 case ARM::VLD1LNdWB_fixed_Asm_32: case ARM::VLD1LNdWB_fixed_Asm_F:
5656 case ARM::VLD1LNdWB_fixed_Asm_F32: case ARM::VLD1LNdWB_fixed_Asm_I32:
5657 case ARM::VLD1LNdWB_fixed_Asm_S32: case ARM::VLD1LNdWB_fixed_Asm_U32: {
Jim Grosbachdda976b2011-12-02 22:01:52 +00005658 MCInst TmpInst;
5659 // Shuffle the operands around so the lane index operand is in the
5660 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005661 unsigned Spacing;
5662 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachdda976b2011-12-02 22:01:52 +00005663 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5664 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5665 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5666 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5667 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5668 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5669 TmpInst.addOperand(Inst.getOperand(1)); // lane
5670 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5671 TmpInst.addOperand(Inst.getOperand(5));
5672 Inst = TmpInst;
5673 return true;
5674 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005675
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005676 case ARM::VLD2LNdWB_fixed_Asm_8: case ARM::VLD2LNdWB_fixed_Asm_P8:
5677 case ARM::VLD2LNdWB_fixed_Asm_I8: case ARM::VLD2LNdWB_fixed_Asm_S8:
5678 case ARM::VLD2LNdWB_fixed_Asm_U8: case ARM::VLD2LNdWB_fixed_Asm_16:
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005679 case ARM::VLD2LNdWB_fixed_Asm_P16: case ARM::VLD2LNdWB_fixed_Asm_I16:
5680 case ARM::VLD2LNdWB_fixed_Asm_S16: case ARM::VLD2LNdWB_fixed_Asm_U16:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005681 case ARM::VLD2LNdWB_fixed_Asm_32: case ARM::VLD2LNdWB_fixed_Asm_F:
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005682 case ARM::VLD2LNdWB_fixed_Asm_F32: case ARM::VLD2LNdWB_fixed_Asm_I32:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005683 case ARM::VLD2LNdWB_fixed_Asm_S32: case ARM::VLD2LNdWB_fixed_Asm_U32:
Jim Grosbach2c590522011-12-20 20:46:29 +00005684 case ARM::VLD2LNqWB_fixed_Asm_16: case ARM::VLD2LNqWB_fixed_Asm_P16:
5685 case ARM::VLD2LNqWB_fixed_Asm_I16: case ARM::VLD2LNqWB_fixed_Asm_S16:
5686 case ARM::VLD2LNqWB_fixed_Asm_U16: case ARM::VLD2LNqWB_fixed_Asm_32:
5687 case ARM::VLD2LNqWB_fixed_Asm_F: case ARM::VLD2LNqWB_fixed_Asm_F32:
5688 case ARM::VLD2LNqWB_fixed_Asm_I32: case ARM::VLD2LNqWB_fixed_Asm_S32:
5689 case ARM::VLD2LNqWB_fixed_Asm_U32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +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 Grosbacha8aa30b2011-12-14 23:25:46 +00005695 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005696 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5697 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005698 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5699 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5700 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5701 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5702 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005703 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5704 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005705 TmpInst.addOperand(Inst.getOperand(1)); // lane
5706 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5707 TmpInst.addOperand(Inst.getOperand(5));
5708 Inst = TmpInst;
5709 return true;
5710 }
5711
Jim Grosbach2c590522011-12-20 20:46:29 +00005712 case ARM::VLD1LNdAsm_8: case ARM::VLD1LNdAsm_P8: case ARM::VLD1LNdAsm_I8:
5713 case ARM::VLD1LNdAsm_S8: case ARM::VLD1LNdAsm_U8: case ARM::VLD1LNdAsm_16:
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005714 case ARM::VLD1LNdAsm_P16: case ARM::VLD1LNdAsm_I16: case ARM::VLD1LNdAsm_S16:
Jim Grosbach2c590522011-12-20 20:46:29 +00005715 case ARM::VLD1LNdAsm_U16: case ARM::VLD1LNdAsm_32: case ARM::VLD1LNdAsm_F:
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005716 case ARM::VLD1LNdAsm_F32: case ARM::VLD1LNdAsm_I32: case ARM::VLD1LNdAsm_S32:
Jim Grosbache7dcbc82011-12-02 18:52:30 +00005717 case ARM::VLD1LNdAsm_U32: {
Jim Grosbach04945c42011-12-02 00:35:16 +00005718 MCInst TmpInst;
5719 // Shuffle the operands around so the lane index operand is in the
5720 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005721 unsigned Spacing;
5722 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach04945c42011-12-02 00:35:16 +00005723 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5724 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5725 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5726 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5727 TmpInst.addOperand(Inst.getOperand(1)); // lane
5728 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5729 TmpInst.addOperand(Inst.getOperand(5));
5730 Inst = TmpInst;
5731 return true;
5732 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005733
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005734 case ARM::VLD2LNdAsm_8: case ARM::VLD2LNdAsm_P8: case ARM::VLD2LNdAsm_I8:
5735 case ARM::VLD2LNdAsm_S8: case ARM::VLD2LNdAsm_U8: case ARM::VLD2LNdAsm_16:
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005736 case ARM::VLD2LNdAsm_P16: case ARM::VLD2LNdAsm_I16: case ARM::VLD2LNdAsm_S16:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005737 case ARM::VLD2LNdAsm_U16: case ARM::VLD2LNdAsm_32: case ARM::VLD2LNdAsm_F:
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005738 case ARM::VLD2LNdAsm_F32: case ARM::VLD2LNdAsm_I32: case ARM::VLD2LNdAsm_S32:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005739 case ARM::VLD2LNdAsm_U32: case ARM::VLD2LNqAsm_16: case ARM::VLD2LNqAsm_P16:
5740 case ARM::VLD2LNqAsm_I16: case ARM::VLD2LNqAsm_S16: case ARM::VLD2LNqAsm_U16:
5741 case ARM::VLD2LNqAsm_32: case ARM::VLD2LNqAsm_F: case ARM::VLD2LNqAsm_F32:
5742 case ARM::VLD2LNqAsm_I32: case ARM::VLD2LNqAsm_S32:
5743 case ARM::VLD2LNqAsm_U32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005744 MCInst TmpInst;
5745 // Shuffle the operands around so the lane index operand is in the
5746 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005747 unsigned Spacing;
5748 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005749 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005750 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5751 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005752 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5753 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5754 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005755 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5756 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005757 TmpInst.addOperand(Inst.getOperand(1)); // lane
5758 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5759 TmpInst.addOperand(Inst.getOperand(5));
5760 Inst = TmpInst;
5761 return true;
5762 }
Jim Grosbach485e5622011-12-13 22:45:11 +00005763 // Handle the Thumb2 mode MOV complex aliases.
Jim Grosbachb3ef7132011-12-21 20:54:00 +00005764 case ARM::t2MOVsr:
5765 case ARM::t2MOVSsr: {
5766 // Which instruction to expand to depends on the CCOut operand and
5767 // whether we're in an IT block if the register operands are low
5768 // registers.
5769 bool isNarrow = false;
5770 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5771 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5772 isARMLowRegister(Inst.getOperand(2).getReg()) &&
5773 Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
5774 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsr))
5775 isNarrow = true;
5776 MCInst TmpInst;
5777 unsigned newOpc;
5778 switch(ARM_AM::getSORegShOp(Inst.getOperand(3).getImm())) {
5779 default: llvm_unreachable("unexpected opcode!");
5780 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRrr : ARM::t2ASRrr; break;
5781 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRrr : ARM::t2LSRrr; break;
5782 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLrr : ARM::t2LSLrr; break;
5783 case ARM_AM::ror: newOpc = isNarrow ? ARM::tROR : ARM::t2RORrr; break;
5784 }
5785 TmpInst.setOpcode(newOpc);
5786 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5787 if (isNarrow)
5788 TmpInst.addOperand(MCOperand::CreateReg(
5789 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
5790 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5791 TmpInst.addOperand(Inst.getOperand(2)); // Rm
5792 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5793 TmpInst.addOperand(Inst.getOperand(5));
5794 if (!isNarrow)
5795 TmpInst.addOperand(MCOperand::CreateReg(
5796 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
5797 Inst = TmpInst;
5798 return true;
5799 }
Jim Grosbach485e5622011-12-13 22:45:11 +00005800 case ARM::t2MOVsi:
5801 case ARM::t2MOVSsi: {
5802 // Which instruction to expand to depends on the CCOut operand and
5803 // whether we're in an IT block if the register operands are low
5804 // registers.
5805 bool isNarrow = false;
5806 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5807 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5808 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
5809 isNarrow = true;
5810 MCInst TmpInst;
5811 unsigned newOpc;
5812 switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
5813 default: llvm_unreachable("unexpected opcode!");
5814 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
5815 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
5816 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
5817 case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
Jim Grosbach8c59bbc2011-12-21 21:04:19 +00005818 case ARM_AM::rrx: isNarrow = false; newOpc = ARM::t2RRX; break;
Jim Grosbach485e5622011-12-13 22:45:11 +00005819 }
5820 unsigned Ammount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
5821 if (Ammount == 32) Ammount = 0;
5822 TmpInst.setOpcode(newOpc);
5823 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5824 if (isNarrow)
5825 TmpInst.addOperand(MCOperand::CreateReg(
5826 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
5827 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbach8c59bbc2011-12-21 21:04:19 +00005828 if (newOpc != ARM::t2RRX)
5829 TmpInst.addOperand(MCOperand::CreateImm(Ammount));
Jim Grosbach485e5622011-12-13 22:45:11 +00005830 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5831 TmpInst.addOperand(Inst.getOperand(4));
5832 if (!isNarrow)
5833 TmpInst.addOperand(MCOperand::CreateReg(
5834 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
5835 Inst = TmpInst;
5836 return true;
5837 }
5838 // Handle the ARM mode MOV complex aliases.
Jim Grosbachabcac562011-11-16 18:31:45 +00005839 case ARM::ASRr:
5840 case ARM::LSRr:
5841 case ARM::LSLr:
5842 case ARM::RORr: {
5843 ARM_AM::ShiftOpc ShiftTy;
5844 switch(Inst.getOpcode()) {
5845 default: llvm_unreachable("unexpected opcode!");
5846 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
5847 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
5848 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
5849 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
5850 }
Jim Grosbachabcac562011-11-16 18:31:45 +00005851 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
5852 MCInst TmpInst;
5853 TmpInst.setOpcode(ARM::MOVsr);
5854 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5855 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5856 TmpInst.addOperand(Inst.getOperand(2)); // Rm
5857 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5858 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5859 TmpInst.addOperand(Inst.getOperand(4));
5860 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5861 Inst = TmpInst;
5862 return true;
5863 }
Jim Grosbachc14871c2011-11-10 19:18:01 +00005864 case ARM::ASRi:
5865 case ARM::LSRi:
5866 case ARM::LSLi:
5867 case ARM::RORi: {
5868 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachc14871c2011-11-10 19:18:01 +00005869 switch(Inst.getOpcode()) {
5870 default: llvm_unreachable("unexpected opcode!");
5871 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
5872 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
5873 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
5874 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
5875 }
5876 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach1a2f9ee2011-11-16 19:05:59 +00005877 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachc14871c2011-11-10 19:18:01 +00005878 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
5879 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach61db5a52011-11-10 16:44:55 +00005880 MCInst TmpInst;
Jim Grosbachc14871c2011-11-10 19:18:01 +00005881 TmpInst.setOpcode(Opc);
Jim Grosbach61db5a52011-11-10 16:44:55 +00005882 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5883 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachc14871c2011-11-10 19:18:01 +00005884 if (Opc == ARM::MOVsi)
5885 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach61db5a52011-11-10 16:44:55 +00005886 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5887 TmpInst.addOperand(Inst.getOperand(4));
5888 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5889 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00005890 return true;
Jim Grosbach61db5a52011-11-10 16:44:55 +00005891 }
Jim Grosbach1a2f9ee2011-11-16 19:05:59 +00005892 case ARM::RRXi: {
5893 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
5894 MCInst TmpInst;
5895 TmpInst.setOpcode(ARM::MOVsi);
5896 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5897 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5898 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5899 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5900 TmpInst.addOperand(Inst.getOperand(3));
5901 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
5902 Inst = TmpInst;
5903 return true;
5904 }
Jim Grosbachd9a9be22011-11-10 23:58:34 +00005905 case ARM::t2LDMIA_UPD: {
5906 // If this is a load of a single register, then we should use
5907 // a post-indexed LDR instruction instead, per the ARM ARM.
5908 if (Inst.getNumOperands() != 5)
5909 return false;
5910 MCInst TmpInst;
5911 TmpInst.setOpcode(ARM::t2LDR_POST);
5912 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5913 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5914 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5915 TmpInst.addOperand(MCOperand::CreateImm(4));
5916 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5917 TmpInst.addOperand(Inst.getOperand(3));
5918 Inst = TmpInst;
5919 return true;
5920 }
5921 case ARM::t2STMDB_UPD: {
5922 // If this is a store of a single register, then we should use
5923 // a pre-indexed STR instruction instead, per the ARM ARM.
5924 if (Inst.getNumOperands() != 5)
5925 return false;
5926 MCInst TmpInst;
5927 TmpInst.setOpcode(ARM::t2STR_PRE);
5928 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5929 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5930 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5931 TmpInst.addOperand(MCOperand::CreateImm(-4));
5932 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5933 TmpInst.addOperand(Inst.getOperand(3));
5934 Inst = TmpInst;
5935 return true;
5936 }
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005937 case ARM::LDMIA_UPD:
5938 // If this is a load of a single register via a 'pop', then we should use
5939 // a post-indexed LDR instruction instead, per the ARM ARM.
5940 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
5941 Inst.getNumOperands() == 5) {
5942 MCInst TmpInst;
5943 TmpInst.setOpcode(ARM::LDR_POST_IMM);
5944 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5945 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5946 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5947 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
5948 TmpInst.addOperand(MCOperand::CreateImm(4));
5949 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5950 TmpInst.addOperand(Inst.getOperand(3));
5951 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00005952 return true;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005953 }
5954 break;
Jim Grosbach27ad83d2011-08-11 18:07:11 +00005955 case ARM::STMDB_UPD:
5956 // If this is a store of a single register via a 'push', then we should use
5957 // a pre-indexed STR instruction instead, per the ARM ARM.
5958 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
5959 Inst.getNumOperands() == 5) {
5960 MCInst TmpInst;
5961 TmpInst.setOpcode(ARM::STR_PRE_IMM);
5962 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5963 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5964 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
5965 TmpInst.addOperand(MCOperand::CreateImm(-4));
5966 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5967 TmpInst.addOperand(Inst.getOperand(3));
5968 Inst = TmpInst;
5969 }
5970 break;
Jim Grosbachec9ba982011-12-05 21:06:26 +00005971 case ARM::t2ADDri12:
5972 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
5973 // mnemonic was used (not "addw"), encoding T3 is preferred.
5974 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
5975 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5976 break;
5977 Inst.setOpcode(ARM::t2ADDri);
5978 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5979 break;
5980 case ARM::t2SUBri12:
5981 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
5982 // mnemonic was used (not "subw"), encoding T3 is preferred.
5983 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
5984 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5985 break;
5986 Inst.setOpcode(ARM::t2SUBri);
5987 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5988 break;
Jim Grosbache9ab47a2011-08-16 23:57:34 +00005989 case ARM::tADDi8:
Jim Grosbach6d606fb2011-08-31 17:07:33 +00005990 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5991 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5992 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5993 // to encoding T1 if <Rd> is omitted."
Jim Grosbachafad0532011-11-10 23:42:14 +00005994 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbache9ab47a2011-08-16 23:57:34 +00005995 Inst.setOpcode(ARM::tADDi3);
Jim Grosbachafad0532011-11-10 23:42:14 +00005996 return true;
5997 }
Jim Grosbache9ab47a2011-08-16 23:57:34 +00005998 break;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00005999 case ARM::tSUBi8:
6000 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6001 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6002 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6003 // to encoding T1 if <Rd> is omitted."
Jim Grosbachafad0532011-11-10 23:42:14 +00006004 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachd0c435c2011-09-16 22:58:42 +00006005 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbachafad0532011-11-10 23:42:14 +00006006 return true;
6007 }
Jim Grosbachd0c435c2011-09-16 22:58:42 +00006008 break;
Jim Grosbache489bab2011-12-05 22:16:39 +00006009 case ARM::t2ADDrr: {
6010 // If the destination and first source operand are the same, and
6011 // there's no setting of the flags, use encoding T2 instead of T3.
6012 // Note that this is only for ADD, not SUB. This mirrors the system
6013 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
6014 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
6015 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbachb8c719c2011-12-05 22:27:04 +00006016 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6017 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbache489bab2011-12-05 22:16:39 +00006018 break;
6019 MCInst TmpInst;
6020 TmpInst.setOpcode(ARM::tADDhirr);
6021 TmpInst.addOperand(Inst.getOperand(0));
6022 TmpInst.addOperand(Inst.getOperand(0));
6023 TmpInst.addOperand(Inst.getOperand(2));
6024 TmpInst.addOperand(Inst.getOperand(3));
6025 TmpInst.addOperand(Inst.getOperand(4));
6026 Inst = TmpInst;
6027 return true;
6028 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00006029 case ARM::tB:
6030 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbachafad0532011-11-10 23:42:14 +00006031 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson29cfe6c2011-09-09 21:48:23 +00006032 Inst.setOpcode(ARM::tBcc);
Jim Grosbachafad0532011-11-10 23:42:14 +00006033 return true;
6034 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00006035 break;
6036 case ARM::t2B:
6037 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbachafad0532011-11-10 23:42:14 +00006038 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson29cfe6c2011-09-09 21:48:23 +00006039 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbachafad0532011-11-10 23:42:14 +00006040 return true;
6041 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00006042 break;
Jim Grosbach99bc8462011-08-31 21:17:31 +00006043 case ARM::t2Bcc:
Jim Grosbacha0d34d32011-09-02 23:22:08 +00006044 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbachafad0532011-11-10 23:42:14 +00006045 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbach99bc8462011-08-31 21:17:31 +00006046 Inst.setOpcode(ARM::t2B);
Jim Grosbachafad0532011-11-10 23:42:14 +00006047 return true;
6048 }
Jim Grosbach99bc8462011-08-31 21:17:31 +00006049 break;
Jim Grosbachcbd4ab12011-08-17 22:57:40 +00006050 case ARM::tBcc:
6051 // If the conditional is AL, we really want tB.
Jim Grosbachafad0532011-11-10 23:42:14 +00006052 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbachcbd4ab12011-08-17 22:57:40 +00006053 Inst.setOpcode(ARM::tB);
Jim Grosbachafad0532011-11-10 23:42:14 +00006054 return true;
6055 }
Jim Grosbach6ddb5682011-08-18 16:08:39 +00006056 break;
Jim Grosbacha31f2232011-09-07 18:05:34 +00006057 case ARM::tLDMIA: {
6058 // If the register list contains any high registers, or if the writeback
6059 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
6060 // instead if we're in Thumb2. Otherwise, this should have generated
6061 // an error in validateInstruction().
6062 unsigned Rn = Inst.getOperand(0).getReg();
6063 bool hasWritebackToken =
6064 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6065 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
6066 bool listContainsBase;
6067 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
6068 (!listContainsBase && !hasWritebackToken) ||
6069 (listContainsBase && hasWritebackToken)) {
6070 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6071 assert (isThumbTwo());
6072 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
6073 // If we're switching to the updating version, we need to insert
6074 // the writeback tied operand.
6075 if (hasWritebackToken)
6076 Inst.insert(Inst.begin(),
6077 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbachafad0532011-11-10 23:42:14 +00006078 return true;
Jim Grosbacha31f2232011-09-07 18:05:34 +00006079 }
6080 break;
6081 }
Jim Grosbach099c9762011-09-16 20:50:13 +00006082 case ARM::tSTMIA_UPD: {
6083 // If the register list contains any high registers, we need to use
6084 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6085 // should have generated an error in validateInstruction().
6086 unsigned Rn = Inst.getOperand(0).getReg();
6087 bool listContainsBase;
6088 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
6089 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6090 assert (isThumbTwo());
6091 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbachafad0532011-11-10 23:42:14 +00006092 return true;
Jim Grosbach099c9762011-09-16 20:50:13 +00006093 }
6094 break;
6095 }
Jim Grosbach9bded9d2011-11-10 23:17:11 +00006096 case ARM::tPOP: {
6097 bool listContainsBase;
6098 // If the register list contains any high registers, we need to use
6099 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6100 // should have generated an error in validateInstruction().
6101 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbachafad0532011-11-10 23:42:14 +00006102 return false;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00006103 assert (isThumbTwo());
6104 Inst.setOpcode(ARM::t2LDMIA_UPD);
6105 // Add the base register and writeback operands.
6106 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6107 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbachafad0532011-11-10 23:42:14 +00006108 return true;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00006109 }
6110 case ARM::tPUSH: {
6111 bool listContainsBase;
6112 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbachafad0532011-11-10 23:42:14 +00006113 return false;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00006114 assert (isThumbTwo());
6115 Inst.setOpcode(ARM::t2STMDB_UPD);
6116 // Add the base register and writeback operands.
6117 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6118 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbachafad0532011-11-10 23:42:14 +00006119 return true;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00006120 }
Jim Grosbachb908b7a2011-09-10 00:15:36 +00006121 case ARM::t2MOVi: {
6122 // If we can use the 16-bit encoding and the user didn't explicitly
6123 // request the 32-bit variant, transform it here.
6124 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6125 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbach18b8b172011-09-14 19:12:11 +00006126 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
6127 Inst.getOperand(4).getReg() == ARM::CPSR) ||
6128 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbachb908b7a2011-09-10 00:15:36 +00006129 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6130 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6131 // The operands aren't in the same order for tMOVi8...
6132 MCInst TmpInst;
6133 TmpInst.setOpcode(ARM::tMOVi8);
6134 TmpInst.addOperand(Inst.getOperand(0));
6135 TmpInst.addOperand(Inst.getOperand(4));
6136 TmpInst.addOperand(Inst.getOperand(1));
6137 TmpInst.addOperand(Inst.getOperand(2));
6138 TmpInst.addOperand(Inst.getOperand(3));
6139 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00006140 return true;
Jim Grosbachb908b7a2011-09-10 00:15:36 +00006141 }
6142 break;
6143 }
6144 case ARM::t2MOVr: {
6145 // If we can use the 16-bit encoding and the user didn't explicitly
6146 // request the 32-bit variant, transform it here.
6147 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6148 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6149 Inst.getOperand(2).getImm() == ARMCC::AL &&
6150 Inst.getOperand(4).getReg() == ARM::CPSR &&
6151 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6152 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6153 // The operands aren't the same for tMOV[S]r... (no cc_out)
6154 MCInst TmpInst;
6155 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
6156 TmpInst.addOperand(Inst.getOperand(0));
6157 TmpInst.addOperand(Inst.getOperand(1));
6158 TmpInst.addOperand(Inst.getOperand(2));
6159 TmpInst.addOperand(Inst.getOperand(3));
6160 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00006161 return true;
Jim Grosbachb908b7a2011-09-10 00:15:36 +00006162 }
6163 break;
6164 }
Jim Grosbach82213192011-09-19 20:29:33 +00006165 case ARM::t2SXTH:
Jim Grosbachb3519802011-09-20 00:46:54 +00006166 case ARM::t2SXTB:
6167 case ARM::t2UXTH:
6168 case ARM::t2UXTB: {
Jim Grosbach82213192011-09-19 20:29:33 +00006169 // If we can use the 16-bit encoding and the user didn't explicitly
6170 // request the 32-bit variant, transform it here.
6171 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6172 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6173 Inst.getOperand(2).getImm() == 0 &&
6174 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6175 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbachb3519802011-09-20 00:46:54 +00006176 unsigned NewOpc;
6177 switch (Inst.getOpcode()) {
6178 default: llvm_unreachable("Illegal opcode!");
6179 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
6180 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
6181 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
6182 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
6183 }
Jim Grosbach82213192011-09-19 20:29:33 +00006184 // The operands aren't the same for thumb1 (no rotate operand).
6185 MCInst TmpInst;
6186 TmpInst.setOpcode(NewOpc);
6187 TmpInst.addOperand(Inst.getOperand(0));
6188 TmpInst.addOperand(Inst.getOperand(1));
6189 TmpInst.addOperand(Inst.getOperand(3));
6190 TmpInst.addOperand(Inst.getOperand(4));
6191 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00006192 return true;
Jim Grosbach82213192011-09-19 20:29:33 +00006193 }
6194 break;
6195 }
Jim Grosbache2ca9e52011-12-20 00:59:38 +00006196 case ARM::MOVsi: {
6197 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm());
6198 if (SOpc == ARM_AM::rrx) return false;
6199 if (ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()) == 0) {
6200 // Shifting by zero is accepted as a vanilla 'MOVr'
6201 MCInst TmpInst;
6202 TmpInst.setOpcode(ARM::MOVr);
6203 TmpInst.addOperand(Inst.getOperand(0));
6204 TmpInst.addOperand(Inst.getOperand(1));
6205 TmpInst.addOperand(Inst.getOperand(3));
6206 TmpInst.addOperand(Inst.getOperand(4));
6207 TmpInst.addOperand(Inst.getOperand(5));
6208 Inst = TmpInst;
6209 return true;
6210 }
6211 return false;
6212 }
Jim Grosbach12ccf452011-12-22 18:04:04 +00006213 case ARM::ANDrsi:
6214 case ARM::ORRrsi:
6215 case ARM::EORrsi:
6216 case ARM::BICrsi:
6217 case ARM::SUBrsi:
6218 case ARM::ADDrsi: {
6219 unsigned newOpc;
6220 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(3).getImm());
6221 if (SOpc == ARM_AM::rrx) return false;
6222 switch (Inst.getOpcode()) {
Matt Beaumont-Gayb982d8e2012-01-03 19:03:59 +00006223 default: assert(0 && "unexpected opcode!");
Jim Grosbach12ccf452011-12-22 18:04:04 +00006224 case ARM::ANDrsi: newOpc = ARM::ANDrr; break;
6225 case ARM::ORRrsi: newOpc = ARM::ORRrr; break;
6226 case ARM::EORrsi: newOpc = ARM::EORrr; break;
6227 case ARM::BICrsi: newOpc = ARM::BICrr; break;
6228 case ARM::SUBrsi: newOpc = ARM::SUBrr; break;
6229 case ARM::ADDrsi: newOpc = ARM::ADDrr; break;
6230 }
6231 // If the shift is by zero, use the non-shifted instruction definition.
6232 if (ARM_AM::getSORegOffset(Inst.getOperand(3).getImm()) == 0) {
6233 MCInst TmpInst;
6234 TmpInst.setOpcode(newOpc);
6235 TmpInst.addOperand(Inst.getOperand(0));
6236 TmpInst.addOperand(Inst.getOperand(1));
6237 TmpInst.addOperand(Inst.getOperand(2));
6238 TmpInst.addOperand(Inst.getOperand(4));
6239 TmpInst.addOperand(Inst.getOperand(5));
6240 TmpInst.addOperand(Inst.getOperand(6));
6241 Inst = TmpInst;
6242 return true;
6243 }
6244 return false;
6245 }
Jim Grosbach3d1eac82011-08-26 21:43:41 +00006246 case ARM::t2IT: {
6247 // The mask bits for all but the first condition are represented as
6248 // the low bit of the condition code value implies 't'. We currently
6249 // always have 1 implies 't', so XOR toggle the bits if the low bit
6250 // of the condition code is zero. The encoding also expects the low
6251 // bit of the condition to be encoded as bit 4 of the mask operand,
6252 // so mask that in if needed
6253 MCOperand &MO = Inst.getOperand(1);
6254 unsigned Mask = MO.getImm();
Jim Grosbached16ec42011-08-29 22:24:09 +00006255 unsigned OrigMask = Mask;
6256 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00006257 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach3d1eac82011-08-26 21:43:41 +00006258 assert(Mask && TZ <= 3 && "illegal IT mask value!");
6259 for (unsigned i = 3; i != TZ; --i)
6260 Mask ^= 1 << i;
6261 } else
6262 Mask |= 0x10;
6263 MO.setImm(Mask);
Jim Grosbached16ec42011-08-29 22:24:09 +00006264
6265 // Set up the IT block state according to the IT instruction we just
6266 // matched.
6267 assert(!inITBlock() && "nested IT blocks?!");
6268 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
6269 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
6270 ITState.CurPosition = 0;
6271 ITState.FirstCond = true;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00006272 break;
6273 }
Jim Grosbach8ba76c62011-08-11 17:35:48 +00006274 }
Jim Grosbachafad0532011-11-10 23:42:14 +00006275 return false;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00006276}
6277
Jim Grosbach3e941ae2011-08-16 20:45:50 +00006278unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
6279 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
6280 // suffix depending on whether they're in an IT block or not.
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00006281 unsigned Opc = Inst.getOpcode();
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00006282 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach3e941ae2011-08-16 20:45:50 +00006283 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
6284 assert(MCID.hasOptionalDef() &&
6285 "optionally flag setting instruction missing optional def operand");
6286 assert(MCID.NumOperands == Inst.getNumOperands() &&
6287 "operand count mismatch!");
6288 // Find the optional-def operand (cc_out).
6289 unsigned OpNo;
6290 for (OpNo = 0;
6291 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
6292 ++OpNo)
6293 ;
6294 // If we're parsing Thumb1, reject it completely.
6295 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
6296 return Match_MnemonicFail;
6297 // If we're parsing Thumb2, which form is legal depends on whether we're
6298 // in an IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00006299 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
6300 !inITBlock())
Jim Grosbach3e941ae2011-08-16 20:45:50 +00006301 return Match_RequiresITBlock;
Jim Grosbached16ec42011-08-29 22:24:09 +00006302 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
6303 inITBlock())
6304 return Match_RequiresNotITBlock;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00006305 }
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00006306 // Some high-register supporting Thumb1 encodings only allow both registers
6307 // to be from r0-r7 when in Thumb2.
6308 else if (Opc == ARM::tADDhirr && isThumbOne() &&
6309 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6310 isARMLowRegister(Inst.getOperand(2).getReg()))
6311 return Match_RequiresThumb2;
6312 // Others only require ARMv6 or later.
Jim Grosbachf86cd372011-08-19 20:46:54 +00006313 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00006314 isARMLowRegister(Inst.getOperand(0).getReg()) &&
6315 isARMLowRegister(Inst.getOperand(1).getReg()))
6316 return Match_RequiresV6;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00006317 return Match_Success;
6318}
6319
Chris Lattner9487de62010-10-28 21:28:01 +00006320bool ARMAsmParser::
6321MatchAndEmitInstruction(SMLoc IDLoc,
6322 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
6323 MCStreamer &Out) {
6324 MCInst Inst;
6325 unsigned ErrorInfo;
Jim Grosbach120a96a2011-08-15 23:03:29 +00006326 unsigned MatchResult;
Kevin Enderby3164a342010-12-09 19:19:43 +00006327 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby3164a342010-12-09 19:19:43 +00006328 switch (MatchResult) {
Jim Grosbach120a96a2011-08-15 23:03:29 +00006329 default: break;
Chris Lattnerd27b05e2010-10-28 21:41:58 +00006330 case Match_Success:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00006331 // Context sensitive operand constraints aren't handled by the matcher,
6332 // so check them here.
Jim Grosbacha0d34d32011-09-02 23:22:08 +00006333 if (validateInstruction(Inst, Operands)) {
6334 // Still progress the IT block, otherwise one wrong condition causes
6335 // nasty cascading errors.
6336 forwardITPosition();
Jim Grosbachedaa35a2011-07-26 18:25:39 +00006337 return true;
Jim Grosbacha0d34d32011-09-02 23:22:08 +00006338 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00006339
Jim Grosbach8ba76c62011-08-11 17:35:48 +00006340 // Some instructions need post-processing to, for example, tweak which
Jim Grosbachafad0532011-11-10 23:42:14 +00006341 // encoding is selected. Loop on it while changes happen so the
6342 // individual transformations can chain off each other. E.g.,
6343 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
6344 while (processInstruction(Inst, Operands))
6345 ;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00006346
Jim Grosbacha0d34d32011-09-02 23:22:08 +00006347 // Only move forward at the very end so that everything in validate
6348 // and process gets a consistent answer about whether we're in an IT
6349 // block.
6350 forwardITPosition();
6351
Chris Lattner9487de62010-10-28 21:28:01 +00006352 Out.EmitInstruction(Inst);
6353 return false;
Chris Lattnerd27b05e2010-10-28 21:41:58 +00006354 case Match_MissingFeature:
6355 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
6356 return true;
6357 case Match_InvalidOperand: {
6358 SMLoc ErrorLoc = IDLoc;
6359 if (ErrorInfo != ~0U) {
6360 if (ErrorInfo >= Operands.size())
6361 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach624bcc72010-10-29 14:46:02 +00006362
Chris Lattnerd27b05e2010-10-28 21:41:58 +00006363 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
6364 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
6365 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00006366
Chris Lattnerd27b05e2010-10-28 21:41:58 +00006367 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattner9487de62010-10-28 21:28:01 +00006368 }
Chris Lattnerd27b05e2010-10-28 21:41:58 +00006369 case Match_MnemonicFail:
Jim Grosbach3e941ae2011-08-16 20:45:50 +00006370 return Error(IDLoc, "invalid instruction");
Daniel Dunbar66193402011-02-04 17:12:23 +00006371 case Match_ConversionFail:
Jim Grosbach8e048492011-08-19 22:07:46 +00006372 // The converter function will have already emited a diagnostic.
6373 return true;
Jim Grosbached16ec42011-08-29 22:24:09 +00006374 case Match_RequiresNotITBlock:
6375 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach3e941ae2011-08-16 20:45:50 +00006376 case Match_RequiresITBlock:
6377 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00006378 case Match_RequiresV6:
6379 return Error(IDLoc, "instruction variant requires ARMv6 or later");
6380 case Match_RequiresThumb2:
6381 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnerd27b05e2010-10-28 21:41:58 +00006382 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00006383
Eric Christopher91d7b902010-10-29 09:26:59 +00006384 llvm_unreachable("Implement any new match types added!");
Chris Lattner9487de62010-10-28 21:28:01 +00006385}
6386
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006387/// parseDirective parses the arm specific directives
Kevin Enderbyccab3172009-09-15 00:27:25 +00006388bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
6389 StringRef IDVal = DirectiveID.getIdentifier();
6390 if (IDVal == ".word")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006391 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00006392 else if (IDVal == ".thumb")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006393 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach7f882392011-12-07 18:04:19 +00006394 else if (IDVal == ".arm")
6395 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00006396 else if (IDVal == ".thumb_func")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006397 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00006398 else if (IDVal == ".code")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006399 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00006400 else if (IDVal == ".syntax")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006401 return parseDirectiveSyntax(DirectiveID.getLoc());
Jim Grosbachab5830e2011-12-14 02:16:11 +00006402 else if (IDVal == ".unreq")
6403 return parseDirectiveUnreq(DirectiveID.getLoc());
Jason W Kim135d2442011-12-20 17:38:12 +00006404 else if (IDVal == ".arch")
6405 return parseDirectiveArch(DirectiveID.getLoc());
6406 else if (IDVal == ".eabi_attribute")
6407 return parseDirectiveEabiAttr(DirectiveID.getLoc());
Kevin Enderbyccab3172009-09-15 00:27:25 +00006408 return true;
6409}
6410
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006411/// parseDirectiveWord
Kevin Enderbyccab3172009-09-15 00:27:25 +00006412/// ::= .word [ expression (, expression)* ]
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006413bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyccab3172009-09-15 00:27:25 +00006414 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6415 for (;;) {
6416 const MCExpr *Value;
6417 if (getParser().ParseExpression(Value))
6418 return true;
6419
Chris Lattnerc35681b2010-01-19 19:46:13 +00006420 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyccab3172009-09-15 00:27:25 +00006421
6422 if (getLexer().is(AsmToken::EndOfStatement))
6423 break;
Jim Grosbach624bcc72010-10-29 14:46:02 +00006424
Kevin Enderbyccab3172009-09-15 00:27:25 +00006425 // FIXME: Improve diagnostic.
6426 if (getLexer().isNot(AsmToken::Comma))
6427 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00006428 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00006429 }
6430 }
6431
Sean Callanana83fd7d2010-01-19 20:27:46 +00006432 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00006433 return false;
6434}
6435
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006436/// parseDirectiveThumb
Kevin Enderby146dcf22009-10-15 20:48:48 +00006437/// ::= .thumb
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006438bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby146dcf22009-10-15 20:48:48 +00006439 if (getLexer().isNot(AsmToken::EndOfStatement))
6440 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00006441 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006442
Jim Grosbach7f882392011-12-07 18:04:19 +00006443 if (!isThumb())
6444 SwitchMode();
6445 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
6446 return false;
6447}
6448
6449/// parseDirectiveARM
6450/// ::= .arm
6451bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
6452 if (getLexer().isNot(AsmToken::EndOfStatement))
6453 return Error(L, "unexpected token in directive");
6454 Parser.Lex();
6455
6456 if (isThumb())
6457 SwitchMode();
6458 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby146dcf22009-10-15 20:48:48 +00006459 return false;
6460}
6461
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006462/// parseDirectiveThumbFunc
Kevin Enderby146dcf22009-10-15 20:48:48 +00006463/// ::= .thumbfunc symbol_name
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006464bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00006465 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
6466 bool isMachO = MAI.hasSubsectionsViaSymbols();
6467 StringRef Name;
Jim Grosbach1152cc02011-12-21 22:30:16 +00006468 bool needFuncName = true;
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00006469
Jim Grosbach1152cc02011-12-21 22:30:16 +00006470 // Darwin asm has (optionally) function name after .thumb_func direction
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00006471 // ELF doesn't
6472 if (isMachO) {
6473 const AsmToken &Tok = Parser.getTok();
Jim Grosbach1152cc02011-12-21 22:30:16 +00006474 if (Tok.isNot(AsmToken::EndOfStatement)) {
6475 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
6476 return Error(L, "unexpected token in .thumb_func directive");
6477 Name = Tok.getIdentifier();
6478 Parser.Lex(); // Consume the identifier token.
6479 needFuncName = false;
6480 }
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00006481 }
6482
Jim Grosbach1152cc02011-12-21 22:30:16 +00006483 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby146dcf22009-10-15 20:48:48 +00006484 return Error(L, "unexpected token in directive");
Jim Grosbach1152cc02011-12-21 22:30:16 +00006485
6486 // Eat the end of statement and any blank lines that follow.
6487 while (getLexer().is(AsmToken::EndOfStatement))
6488 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006489
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00006490 // FIXME: assuming function name will be the line following .thumb_func
Jim Grosbach1152cc02011-12-21 22:30:16 +00006491 // We really should be checking the next symbol definition even if there's
6492 // stuff in between.
6493 if (needFuncName) {
Jim Grosbach42ba6282011-11-10 20:48:53 +00006494 Name = Parser.getTok().getIdentifier();
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00006495 }
6496
Jim Grosbachc6db8ce2010-11-05 22:33:53 +00006497 // Mark symbol as a thumb symbol.
6498 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
6499 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby146dcf22009-10-15 20:48:48 +00006500 return false;
6501}
6502
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006503/// parseDirectiveSyntax
Kevin Enderby146dcf22009-10-15 20:48:48 +00006504/// ::= .syntax unified | divided
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006505bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00006506 const AsmToken &Tok = Parser.getTok();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006507 if (Tok.isNot(AsmToken::Identifier))
6508 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer92d89982010-07-14 22:38:02 +00006509 StringRef Mode = Tok.getString();
Duncan Sands257eba42010-06-29 13:04:35 +00006510 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callanana83fd7d2010-01-19 20:27:46 +00006511 Parser.Lex();
Duncan Sands257eba42010-06-29 13:04:35 +00006512 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderbye9f2f0c2011-01-27 23:22:36 +00006513 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby146dcf22009-10-15 20:48:48 +00006514 else
6515 return Error(L, "unrecognized syntax mode in .syntax directive");
6516
6517 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan936b0d32010-01-19 21:44:56 +00006518 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00006519 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006520
6521 // TODO tell the MC streamer the mode
6522 // getParser().getStreamer().Emit???();
6523 return false;
6524}
6525
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006526/// parseDirectiveCode
Kevin Enderby146dcf22009-10-15 20:48:48 +00006527/// ::= .code 16 | 32
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006528bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00006529 const AsmToken &Tok = Parser.getTok();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006530 if (Tok.isNot(AsmToken::Integer))
6531 return Error(L, "unexpected token in .code directive");
Sean Callanan936b0d32010-01-19 21:44:56 +00006532 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands257eba42010-06-29 13:04:35 +00006533 if (Val == 16)
Sean Callanana83fd7d2010-01-19 20:27:46 +00006534 Parser.Lex();
Duncan Sands257eba42010-06-29 13:04:35 +00006535 else if (Val == 32)
Sean Callanana83fd7d2010-01-19 20:27:46 +00006536 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006537 else
6538 return Error(L, "invalid operand to .code directive");
6539
6540 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan936b0d32010-01-19 21:44:56 +00006541 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00006542 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006543
Evan Cheng284b4672011-07-08 22:36:29 +00006544 if (Val == 16) {
Jim Grosbachf471ac32011-09-06 18:46:23 +00006545 if (!isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00006546 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00006547 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng284b4672011-07-08 22:36:29 +00006548 } else {
Jim Grosbachf471ac32011-09-06 18:46:23 +00006549 if (isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00006550 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00006551 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Cheng45543ba2011-07-08 22:49:55 +00006552 }
Jim Grosbach2db0ea02010-11-05 22:40:53 +00006553
Kevin Enderby146dcf22009-10-15 20:48:48 +00006554 return false;
6555}
6556
Jim Grosbachab5830e2011-12-14 02:16:11 +00006557/// parseDirectiveReq
6558/// ::= name .req registername
6559bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
6560 Parser.Lex(); // Eat the '.req' token.
6561 unsigned Reg;
6562 SMLoc SRegLoc, ERegLoc;
6563 if (ParseRegister(Reg, SRegLoc, ERegLoc)) {
6564 Parser.EatToEndOfStatement();
6565 return Error(SRegLoc, "register name expected");
6566 }
6567
6568 // Shouldn't be anything else.
6569 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
6570 Parser.EatToEndOfStatement();
6571 return Error(Parser.getTok().getLoc(),
6572 "unexpected input in .req directive.");
6573 }
6574
6575 Parser.Lex(); // Consume the EndOfStatement
6576
6577 if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg)
6578 return Error(SRegLoc, "redefinition of '" + Name +
6579 "' does not match original.");
6580
6581 return false;
6582}
6583
6584/// parseDirectiveUneq
6585/// ::= .unreq registername
6586bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
6587 if (Parser.getTok().isNot(AsmToken::Identifier)) {
6588 Parser.EatToEndOfStatement();
6589 return Error(L, "unexpected input in .unreq directive.");
6590 }
6591 RegisterReqs.erase(Parser.getTok().getIdentifier());
6592 Parser.Lex(); // Eat the identifier.
6593 return false;
6594}
6595
Jason W Kim135d2442011-12-20 17:38:12 +00006596/// parseDirectiveArch
6597/// ::= .arch token
6598bool ARMAsmParser::parseDirectiveArch(SMLoc L) {
6599 return true;
6600}
6601
6602/// parseDirectiveEabiAttr
6603/// ::= .eabi_attribute int, int
6604bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
6605 return true;
6606}
6607
Sean Callanan643a5572010-04-07 20:29:34 +00006608extern "C" void LLVMInitializeARMAsmLexer();
6609
Kevin Enderby8be42bd2009-10-30 22:55:57 +00006610/// Force static initialization.
Kevin Enderbyccab3172009-09-15 00:27:25 +00006611extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng11424442011-07-26 00:24:13 +00006612 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
6613 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan643a5572010-04-07 20:29:34 +00006614 LLVMInitializeARMAsmLexer();
Kevin Enderbyccab3172009-09-15 00:27:25 +00006615}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00006616
Chris Lattner3e4582a2010-09-06 19:11:01 +00006617#define GET_REGISTER_MATCHER
6618#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00006619#include "ARMGenAsmMatcher.inc"