blob: 94631890accb2cf92fda0f032d6ecda901b009ef [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,
273 k_FPImmediate,
274 k_MemBarrierOpt,
275 k_Memory,
276 k_PostIndexRegister,
277 k_MSRMask,
278 k_ProcIFlags,
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000279 k_VectorIndex,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000280 k_Register,
281 k_RegisterList,
282 k_DPRRegisterList,
283 k_SPRRegisterList,
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000284 k_VectorList,
Jim Grosbachcd6f5e72011-11-30 01:09:44 +0000285 k_VectorListAllLanes,
Jim Grosbach04945c42011-12-02 00:35:16 +0000286 k_VectorListIndexed,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000287 k_ShiftedRegister,
288 k_ShiftedImmediate,
289 k_ShifterImmediate,
290 k_RotateImmediate,
291 k_BitfieldDescriptor,
292 k_Token
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000293 } Kind;
294
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000295 SMLoc StartLoc, EndLoc;
Bill Wendling0ab0f672010-11-18 21:50:54 +0000296 SmallVector<unsigned, 8> Registers;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000297
298 union {
299 struct {
Daniel Dunbard8042b72010-08-11 06:36:53 +0000300 ARMCC::CondCodes Val;
301 } CC;
302
303 struct {
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000304 unsigned Val;
305 } Cop;
306
307 struct {
Jim Grosbach48399582011-10-12 17:34:41 +0000308 unsigned Val;
309 } CoprocOption;
310
311 struct {
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000312 unsigned Mask:4;
313 } ITMask;
314
315 struct {
316 ARM_MB::MemBOpt Val;
317 } MBOpt;
318
319 struct {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000320 ARM_PROC::IFlags Val;
321 } IFlags;
322
323 struct {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000324 unsigned Val;
325 } MMask;
326
327 struct {
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000328 const char *Data;
329 unsigned Length;
330 } Tok;
331
332 struct {
333 unsigned RegNum;
334 } Reg;
335
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000336 // A vector register list is a sequential list of 1 to 4 registers.
337 struct {
338 unsigned RegNum;
339 unsigned Count;
Jim Grosbach04945c42011-12-02 00:35:16 +0000340 unsigned LaneIndex;
Jim Grosbach2f50e922011-12-15 21:44:33 +0000341 bool isDoubleSpaced;
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000342 } VectorList;
343
Bill Wendlingb884a8e2010-11-06 22:19:43 +0000344 struct {
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000345 unsigned Val;
346 } VectorIndex;
347
348 struct {
Kevin Enderbyf5079942009-10-13 22:19:02 +0000349 const MCExpr *Val;
350 } Imm;
Jim Grosbach624bcc72010-10-29 14:46:02 +0000351
Jim Grosbache7fbce72011-10-03 23:38:36 +0000352 struct {
353 unsigned Val; // encoded 8-bit representation
354 } FPImm;
355
Daniel Dunbar2be732a2011-01-10 15:26:21 +0000356 /// Combined record for all forms of ARM address expressions.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000357 struct {
358 unsigned BaseRegNum;
Jim Grosbachd3595712011-08-03 23:50:40 +0000359 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
360 // was specified.
361 const MCConstantExpr *OffsetImm; // Offset immediate value
362 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
363 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbacha95ec992011-10-11 17:29:55 +0000364 unsigned ShiftImm; // shift for OffsetReg.
365 unsigned Alignment; // 0 = no alignment specified
Jim Grosbachcef98cd2011-12-19 18:31:43 +0000366 // n = alignment in bytes (2, 4, 8, 16, or 32)
Jim Grosbachd3595712011-08-03 23:50:40 +0000367 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbach871dff72011-10-11 15:59:20 +0000368 } Memory;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000369
370 struct {
Jim Grosbachd3595712011-08-03 23:50:40 +0000371 unsigned RegNum;
Jim Grosbachc320c852011-08-05 21:28:30 +0000372 bool isAdd;
373 ARM_AM::ShiftOpc ShiftTy;
374 unsigned ShiftImm;
Jim Grosbachd3595712011-08-03 23:50:40 +0000375 } PostIdxReg;
376
377 struct {
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000378 bool isASR;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000379 unsigned Imm;
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000380 } ShifterImm;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000381 struct {
382 ARM_AM::ShiftOpc ShiftTy;
383 unsigned SrcReg;
384 unsigned ShiftReg;
385 unsigned ShiftImm;
Jim Grosbachac798e12011-07-25 20:49:51 +0000386 } RegShiftedReg;
Owen Andersonb595ed02011-07-21 18:54:16 +0000387 struct {
388 ARM_AM::ShiftOpc ShiftTy;
389 unsigned SrcReg;
390 unsigned ShiftImm;
Jim Grosbachac798e12011-07-25 20:49:51 +0000391 } RegShiftedImm;
Jim Grosbach833b9d32011-07-27 20:15:40 +0000392 struct {
393 unsigned Imm;
394 } RotImm;
Jim Grosbach864b6092011-07-28 21:34:26 +0000395 struct {
396 unsigned LSB;
397 unsigned Width;
398 } Bitfield;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000399 };
Jim Grosbach624bcc72010-10-29 14:46:02 +0000400
Bill Wendlingee7f1f92010-11-06 21:42:12 +0000401 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
402public:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000403 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
404 Kind = o.Kind;
405 StartLoc = o.StartLoc;
406 EndLoc = o.EndLoc;
407 switch (Kind) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000408 case k_CondCode:
Daniel Dunbard8042b72010-08-11 06:36:53 +0000409 CC = o.CC;
410 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000411 case k_ITCondMask:
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000412 ITMask = o.ITMask;
413 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000414 case k_Token:
Daniel Dunbard8042b72010-08-11 06:36:53 +0000415 Tok = o.Tok;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000416 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000417 case k_CCOut:
418 case k_Register:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000419 Reg = o.Reg;
420 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000421 case k_RegisterList:
422 case k_DPRRegisterList:
423 case k_SPRRegisterList:
Bill Wendling0ab0f672010-11-18 21:50:54 +0000424 Registers = o.Registers;
Bill Wendling7cef4472010-11-06 19:56:04 +0000425 break;
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000426 case k_VectorList:
Jim Grosbachcd6f5e72011-11-30 01:09:44 +0000427 case k_VectorListAllLanes:
Jim Grosbach04945c42011-12-02 00:35:16 +0000428 case k_VectorListIndexed:
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000429 VectorList = o.VectorList;
430 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000431 case k_CoprocNum:
432 case k_CoprocReg:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000433 Cop = o.Cop;
434 break;
Jim Grosbach48399582011-10-12 17:34:41 +0000435 case k_CoprocOption:
436 CoprocOption = o.CoprocOption;
437 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000438 case k_Immediate:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000439 Imm = o.Imm;
440 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000441 case k_FPImmediate:
Jim Grosbache7fbce72011-10-03 23:38:36 +0000442 FPImm = o.FPImm;
443 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000444 case k_MemBarrierOpt:
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000445 MBOpt = o.MBOpt;
446 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000447 case k_Memory:
Jim Grosbach871dff72011-10-11 15:59:20 +0000448 Memory = o.Memory;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000449 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000450 case k_PostIndexRegister:
Jim Grosbachd3595712011-08-03 23:50:40 +0000451 PostIdxReg = o.PostIdxReg;
452 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000453 case k_MSRMask:
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000454 MMask = o.MMask;
455 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000456 case k_ProcIFlags:
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000457 IFlags = o.IFlags;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000458 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000459 case k_ShifterImmediate:
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000460 ShifterImm = o.ShifterImm;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000461 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000462 case k_ShiftedRegister:
Jim Grosbachac798e12011-07-25 20:49:51 +0000463 RegShiftedReg = o.RegShiftedReg;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000464 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000465 case k_ShiftedImmediate:
Jim Grosbachac798e12011-07-25 20:49:51 +0000466 RegShiftedImm = o.RegShiftedImm;
Owen Andersonb595ed02011-07-21 18:54:16 +0000467 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000468 case k_RotateImmediate:
Jim Grosbach833b9d32011-07-27 20:15:40 +0000469 RotImm = o.RotImm;
470 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000471 case k_BitfieldDescriptor:
Jim Grosbach864b6092011-07-28 21:34:26 +0000472 Bitfield = o.Bitfield;
473 break;
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000474 case k_VectorIndex:
475 VectorIndex = o.VectorIndex;
476 break;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000477 }
478 }
Jim Grosbach624bcc72010-10-29 14:46:02 +0000479
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000480 /// getStartLoc - Get the location of the first token of this operand.
481 SMLoc getStartLoc() const { return StartLoc; }
482 /// getEndLoc - Get the location of the last token of this operand.
483 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000484
Daniel Dunbard8042b72010-08-11 06:36:53 +0000485 ARMCC::CondCodes getCondCode() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000486 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbard8042b72010-08-11 06:36:53 +0000487 return CC.Val;
488 }
489
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000490 unsigned getCoproc() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000491 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000492 return Cop.Val;
493 }
494
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000495 StringRef getToken() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000496 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000497 return StringRef(Tok.Data, Tok.Length);
498 }
499
500 unsigned getReg() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000501 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling2cae3272010-11-09 22:44:22 +0000502 return Reg.RegNum;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000503 }
504
Bill Wendlingbed94652010-11-09 23:28:44 +0000505 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000506 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
507 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling0ab0f672010-11-18 21:50:54 +0000508 return Registers;
Bill Wendling7cef4472010-11-06 19:56:04 +0000509 }
510
Kevin Enderbyf5079942009-10-13 22:19:02 +0000511 const MCExpr *getImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000512 assert(Kind == k_Immediate && "Invalid access!");
Kevin Enderbyf5079942009-10-13 22:19:02 +0000513 return Imm.Val;
514 }
515
Jim Grosbache7fbce72011-10-03 23:38:36 +0000516 unsigned getFPImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000517 assert(Kind == k_FPImmediate && "Invalid access!");
Jim Grosbache7fbce72011-10-03 23:38:36 +0000518 return FPImm.Val;
519 }
520
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000521 unsigned getVectorIndex() const {
522 assert(Kind == k_VectorIndex && "Invalid access!");
523 return VectorIndex.Val;
524 }
525
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000526 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000527 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000528 return MBOpt.Val;
529 }
530
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000531 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000532 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000533 return IFlags.Val;
534 }
535
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000536 unsigned getMSRMask() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000537 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000538 return MMask.Val;
539 }
540
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000541 bool isCoprocNum() const { return Kind == k_CoprocNum; }
542 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach48399582011-10-12 17:34:41 +0000543 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000544 bool isCondCode() const { return Kind == k_CondCode; }
545 bool isCCOut() const { return Kind == k_CCOut; }
546 bool isITMask() const { return Kind == k_ITCondMask; }
547 bool isITCondCode() const { return Kind == k_CondCode; }
548 bool isImm() const { return Kind == k_Immediate; }
549 bool isFPImm() const { return Kind == k_FPImmediate; }
Jim Grosbach7db8d692011-09-08 22:07:06 +0000550 bool isImm8s4() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000551 if (Kind != k_Immediate)
Jim Grosbach7db8d692011-09-08 22:07:06 +0000552 return false;
553 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
554 if (!CE) return false;
555 int64_t Value = CE->getValue();
556 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
557 }
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000558 bool isImm0_1020s4() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000559 if (Kind != k_Immediate)
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000560 return false;
561 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
562 if (!CE) return false;
563 int64_t Value = CE->getValue();
564 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
565 }
566 bool isImm0_508s4() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000567 if (Kind != k_Immediate)
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000568 return false;
569 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
570 if (!CE) return false;
571 int64_t Value = CE->getValue();
572 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
573 }
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000574 bool isImm0_255() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000575 if (Kind != k_Immediate)
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000576 return false;
577 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
578 if (!CE) return false;
579 int64_t Value = CE->getValue();
580 return Value >= 0 && Value < 256;
581 }
Jim Grosbach9dff9f42011-12-02 23:34:39 +0000582 bool isImm0_1() const {
583 if (Kind != k_Immediate)
584 return false;
585 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
586 if (!CE) return false;
587 int64_t Value = CE->getValue();
588 return Value >= 0 && Value < 2;
589 }
590 bool isImm0_3() const {
591 if (Kind != k_Immediate)
592 return false;
593 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
594 if (!CE) return false;
595 int64_t Value = CE->getValue();
596 return Value >= 0 && Value < 4;
597 }
Jim Grosbach31756c22011-07-13 22:01:08 +0000598 bool isImm0_7() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000599 if (Kind != k_Immediate)
Jim Grosbach31756c22011-07-13 22:01:08 +0000600 return false;
601 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
602 if (!CE) return false;
603 int64_t Value = CE->getValue();
604 return Value >= 0 && Value < 8;
605 }
606 bool isImm0_15() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000607 if (Kind != k_Immediate)
Jim Grosbach31756c22011-07-13 22:01:08 +0000608 return false;
609 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
610 if (!CE) return false;
611 int64_t Value = CE->getValue();
612 return Value >= 0 && Value < 16;
613 }
Jim Grosbach72e7c4f2011-07-21 23:26:25 +0000614 bool isImm0_31() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000615 if (Kind != k_Immediate)
Jim Grosbach72e7c4f2011-07-21 23:26:25 +0000616 return false;
617 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
618 if (!CE) return false;
619 int64_t Value = CE->getValue();
620 return Value >= 0 && Value < 32;
621 }
Jim Grosbach00326402011-12-08 01:30:04 +0000622 bool isImm0_63() const {
623 if (Kind != k_Immediate)
624 return false;
625 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
626 if (!CE) return false;
627 int64_t Value = CE->getValue();
628 return Value >= 0 && Value < 64;
629 }
Jim Grosbachd4b82492011-12-07 01:07:24 +0000630 bool isImm8() const {
631 if (Kind != k_Immediate)
632 return false;
633 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
634 if (!CE) return false;
635 int64_t Value = CE->getValue();
636 return Value == 8;
637 }
638 bool isImm16() const {
639 if (Kind != k_Immediate)
640 return false;
641 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
642 if (!CE) return false;
643 int64_t Value = CE->getValue();
644 return Value == 16;
645 }
646 bool isImm32() const {
647 if (Kind != k_Immediate)
648 return false;
649 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
650 if (!CE) return false;
651 int64_t Value = CE->getValue();
652 return Value == 32;
653 }
Jim Grosbachba7d6ed2011-12-08 22:06:06 +0000654 bool isShrImm8() const {
655 if (Kind != k_Immediate)
656 return false;
657 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
658 if (!CE) return false;
659 int64_t Value = CE->getValue();
660 return Value > 0 && Value <= 8;
661 }
662 bool isShrImm16() const {
663 if (Kind != k_Immediate)
664 return false;
665 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
666 if (!CE) return false;
667 int64_t Value = CE->getValue();
668 return Value > 0 && Value <= 16;
669 }
670 bool isShrImm32() const {
671 if (Kind != k_Immediate)
672 return false;
673 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
674 if (!CE) return false;
675 int64_t Value = CE->getValue();
676 return Value > 0 && Value <= 32;
677 }
678 bool isShrImm64() const {
679 if (Kind != k_Immediate)
680 return false;
681 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
682 if (!CE) return false;
683 int64_t Value = CE->getValue();
684 return Value > 0 && Value <= 64;
685 }
Jim Grosbachd4b82492011-12-07 01:07:24 +0000686 bool isImm1_7() const {
687 if (Kind != k_Immediate)
688 return false;
689 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
690 if (!CE) return false;
691 int64_t Value = CE->getValue();
692 return Value > 0 && Value < 8;
693 }
694 bool isImm1_15() const {
695 if (Kind != k_Immediate)
696 return false;
697 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
698 if (!CE) return false;
699 int64_t Value = CE->getValue();
700 return Value > 0 && Value < 16;
701 }
702 bool isImm1_31() const {
703 if (Kind != k_Immediate)
704 return false;
705 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
706 if (!CE) return false;
707 int64_t Value = CE->getValue();
708 return Value > 0 && Value < 32;
709 }
Jim Grosbach475c6db2011-07-25 23:09:14 +0000710 bool isImm1_16() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000711 if (Kind != k_Immediate)
Jim Grosbach475c6db2011-07-25 23:09:14 +0000712 return false;
713 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
714 if (!CE) return false;
715 int64_t Value = CE->getValue();
716 return Value > 0 && Value < 17;
717 }
Jim Grosbach801e0a32011-07-22 23:16:18 +0000718 bool isImm1_32() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000719 if (Kind != k_Immediate)
Jim Grosbach801e0a32011-07-22 23:16:18 +0000720 return false;
721 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
722 if (!CE) return false;
723 int64_t Value = CE->getValue();
724 return Value > 0 && Value < 33;
725 }
Jim Grosbachc14871c2011-11-10 19:18:01 +0000726 bool isImm0_32() const {
727 if (Kind != k_Immediate)
728 return false;
729 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
730 if (!CE) return false;
731 int64_t Value = CE->getValue();
732 return Value >= 0 && Value < 33;
733 }
Jim Grosbach975b6412011-07-13 20:10:10 +0000734 bool isImm0_65535() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000735 if (Kind != k_Immediate)
Jim Grosbach975b6412011-07-13 20:10:10 +0000736 return false;
737 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
738 if (!CE) return false;
739 int64_t Value = CE->getValue();
740 return Value >= 0 && Value < 65536;
741 }
Jim Grosbach7c09e3c2011-07-19 19:13:28 +0000742 bool isImm0_65535Expr() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000743 if (Kind != k_Immediate)
Jim Grosbach7c09e3c2011-07-19 19:13:28 +0000744 return false;
745 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
746 // If it's not a constant expression, it'll generate a fixup and be
747 // handled later.
748 if (!CE) return true;
749 int64_t Value = CE->getValue();
750 return Value >= 0 && Value < 65536;
751 }
Jim Grosbachf1637842011-07-26 16:24:27 +0000752 bool isImm24bit() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000753 if (Kind != k_Immediate)
Jim Grosbachf1637842011-07-26 16:24:27 +0000754 return false;
755 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
756 if (!CE) return false;
757 int64_t Value = CE->getValue();
758 return Value >= 0 && Value <= 0xffffff;
759 }
Jim Grosbach46dd4132011-08-17 21:51:27 +0000760 bool isImmThumbSR() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000761 if (Kind != k_Immediate)
Jim Grosbach46dd4132011-08-17 21:51:27 +0000762 return false;
763 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
764 if (!CE) return false;
765 int64_t Value = CE->getValue();
766 return Value > 0 && Value < 33;
767 }
Jim Grosbach27c1e252011-07-21 17:23:04 +0000768 bool isPKHLSLImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000769 if (Kind != k_Immediate)
Jim Grosbach27c1e252011-07-21 17:23:04 +0000770 return false;
771 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
772 if (!CE) return false;
773 int64_t Value = CE->getValue();
774 return Value >= 0 && Value < 32;
775 }
776 bool isPKHASRImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000777 if (Kind != k_Immediate)
Jim Grosbach27c1e252011-07-21 17:23:04 +0000778 return false;
779 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
780 if (!CE) return false;
781 int64_t Value = CE->getValue();
782 return Value > 0 && Value <= 32;
783 }
Jim Grosbach9720dcf2011-07-19 16:50:30 +0000784 bool isARMSOImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000785 if (Kind != k_Immediate)
Jim Grosbach9720dcf2011-07-19 16:50:30 +0000786 return false;
787 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
788 if (!CE) return false;
789 int64_t Value = CE->getValue();
790 return ARM_AM::getSOImmVal(Value) != -1;
791 }
Jim Grosbach3d785ed2011-10-28 22:50:54 +0000792 bool isARMSOImmNot() const {
793 if (Kind != k_Immediate)
794 return false;
795 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
796 if (!CE) return false;
797 int64_t Value = CE->getValue();
798 return ARM_AM::getSOImmVal(~Value) != -1;
799 }
Jim Grosbach30506252011-12-08 00:31:07 +0000800 bool isARMSOImmNeg() const {
801 if (Kind != k_Immediate)
802 return false;
803 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
804 if (!CE) return false;
805 int64_t Value = CE->getValue();
806 return ARM_AM::getSOImmVal(-Value) != -1;
807 }
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000808 bool isT2SOImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000809 if (Kind != k_Immediate)
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000810 return false;
811 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
812 if (!CE) return false;
813 int64_t Value = CE->getValue();
814 return ARM_AM::getT2SOImmVal(Value) != -1;
815 }
Jim Grosbachb009a872011-10-28 22:36:30 +0000816 bool isT2SOImmNot() const {
817 if (Kind != k_Immediate)
818 return false;
819 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
820 if (!CE) return false;
821 int64_t Value = CE->getValue();
822 return ARM_AM::getT2SOImmVal(~Value) != -1;
823 }
Jim Grosbach30506252011-12-08 00:31:07 +0000824 bool isT2SOImmNeg() const {
825 if (Kind != k_Immediate)
826 return false;
827 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
828 if (!CE) return false;
829 int64_t Value = CE->getValue();
830 return ARM_AM::getT2SOImmVal(-Value) != -1;
831 }
Jim Grosbach0a547702011-07-22 17:44:50 +0000832 bool isSetEndImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000833 if (Kind != k_Immediate)
Jim Grosbach0a547702011-07-22 17:44:50 +0000834 return false;
835 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
836 if (!CE) return false;
837 int64_t Value = CE->getValue();
838 return Value == 1 || Value == 0;
839 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000840 bool isReg() const { return Kind == k_Register; }
841 bool isRegList() const { return Kind == k_RegisterList; }
842 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
843 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
844 bool isToken() const { return Kind == k_Token; }
845 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
846 bool isMemory() const { return Kind == k_Memory; }
847 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
848 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
849 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
850 bool isRotImm() const { return Kind == k_RotateImmediate; }
851 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
852 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachc320c852011-08-05 21:28:30 +0000853 bool isPostIdxReg() const {
Jim Grosbachee201fa2011-11-14 17:52:47 +0000854 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachc320c852011-08-05 21:28:30 +0000855 }
Jim Grosbacha95ec992011-10-11 17:29:55 +0000856 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachc11b7c32011-10-10 23:06:42 +0000857 if (!isMemory())
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000858 return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000859 // No offset of any kind.
Jim Grosbacha95ec992011-10-11 17:29:55 +0000860 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
861 (alignOK || Memory.Alignment == 0);
862 }
863 bool isAlignedMemory() const {
864 return isMemNoOffset(true);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000865 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000866 bool isAddrMode2() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000867 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000868 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000869 if (Memory.OffsetRegNum) return true;
Jim Grosbachd3595712011-08-03 23:50:40 +0000870 // Immediate offset in range [-4095, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +0000871 if (!Memory.OffsetImm) return true;
872 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachd3595712011-08-03 23:50:40 +0000873 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +0000874 }
Jim Grosbachcd17c122011-08-04 23:01:30 +0000875 bool isAM2OffsetImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000876 if (Kind != k_Immediate)
Jim Grosbachcd17c122011-08-04 23:01:30 +0000877 return false;
878 // Immediate offset in range [-4095, 4095].
879 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
880 if (!CE) return false;
881 int64_t Val = CE->getValue();
882 return Val > -4096 && Val < 4096;
883 }
Jim Grosbach5b96b802011-08-10 20:29:19 +0000884 bool isAddrMode3() const {
Jim Grosbach8648c102011-12-19 23:06:24 +0000885 // If we have an immediate that's not a constant, treat it as a label
886 // reference needing a fixup. If it is a constant, it's something else
887 // and we reject it.
888 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
889 return true;
Jim Grosbacha95ec992011-10-11 17:29:55 +0000890 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000891 // No shifts are legal for AM3.
Jim Grosbach871dff72011-10-11 15:59:20 +0000892 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000893 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000894 if (Memory.OffsetRegNum) return true;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000895 // Immediate offset in range [-255, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +0000896 if (!Memory.OffsetImm) return true;
897 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach5b96b802011-08-10 20:29:19 +0000898 return Val > -256 && Val < 256;
899 }
900 bool isAM3Offset() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000901 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach5b96b802011-08-10 20:29:19 +0000902 return false;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000903 if (Kind == k_PostIndexRegister)
Jim Grosbach5b96b802011-08-10 20:29:19 +0000904 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
905 // Immediate offset in range [-255, 255].
906 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
907 if (!CE) return false;
908 int64_t Val = CE->getValue();
Jim Grosbach1d9d5e92011-08-10 21:56:18 +0000909 // Special case, #-0 is INT32_MIN.
910 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000911 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000912 bool isAddrMode5() const {
Jim Grosbachfb2f1d62011-11-01 01:24:45 +0000913 // If we have an immediate that's not a constant, treat it as a label
914 // reference needing a fixup. If it is a constant, it's something else
915 // and we reject it.
916 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
917 return true;
Jim Grosbacha95ec992011-10-11 17:29:55 +0000918 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000919 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000920 if (Memory.OffsetRegNum) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000921 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbach871dff72011-10-11 15:59:20 +0000922 if (!Memory.OffsetImm) return true;
923 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson967674d2011-08-29 19:36:44 +0000924 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbachfb2f1d62011-11-01 01:24:45 +0000925 Val == INT32_MIN;
Bill Wendling8d2aa032010-11-08 23:49:57 +0000926 }
Jim Grosbach05541f42011-09-19 22:21:13 +0000927 bool isMemTBB() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000928 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000929 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach05541f42011-09-19 22:21:13 +0000930 return false;
931 return true;
932 }
933 bool isMemTBH() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000934 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000935 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
936 Memory.Alignment != 0 )
Jim Grosbach05541f42011-09-19 22:21:13 +0000937 return false;
938 return true;
939 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000940 bool isMemRegOffset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000941 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendling092a7bd2010-12-14 03:36:38 +0000942 return false;
Daniel Dunbar7ed45592011-01-18 05:34:11 +0000943 return true;
Bill Wendling092a7bd2010-12-14 03:36:38 +0000944 }
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000945 bool isT2MemRegOffset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000946 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
947 Memory.Alignment != 0)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000948 return false;
949 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbach871dff72011-10-11 15:59:20 +0000950 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000951 return true;
Jim Grosbach871dff72011-10-11 15:59:20 +0000952 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000953 return false;
954 return true;
955 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000956 bool isMemThumbRR() const {
957 // Thumb reg+reg addressing is simple. Just two registers, a base and
958 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbach871dff72011-10-11 15:59:20 +0000959 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000960 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendling811c9362010-11-30 07:44:32 +0000961 return false;
Jim Grosbach871dff72011-10-11 15:59:20 +0000962 return isARMLowRegister(Memory.BaseRegNum) &&
963 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach3fe94e32011-08-19 17:55:24 +0000964 }
965 bool isMemThumbRIs4() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000966 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000967 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach3fe94e32011-08-19 17:55:24 +0000968 return false;
969 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbach871dff72011-10-11 15:59:20 +0000970 if (!Memory.OffsetImm) return true;
971 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach23983d62011-08-19 18:13:48 +0000972 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
973 }
Jim Grosbach26d35872011-08-19 18:55:51 +0000974 bool isMemThumbRIs2() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000975 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000976 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach26d35872011-08-19 18:55:51 +0000977 return false;
978 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbach871dff72011-10-11 15:59:20 +0000979 if (!Memory.OffsetImm) return true;
980 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach26d35872011-08-19 18:55:51 +0000981 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
982 }
Jim Grosbacha32c7532011-08-19 18:49:59 +0000983 bool isMemThumbRIs1() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000984 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000985 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbacha32c7532011-08-19 18:49:59 +0000986 return false;
987 // Immediate offset in range [0, 31].
Jim Grosbach871dff72011-10-11 15:59:20 +0000988 if (!Memory.OffsetImm) return true;
989 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha32c7532011-08-19 18:49:59 +0000990 return Val >= 0 && Val <= 31;
991 }
Jim Grosbach23983d62011-08-19 18:13:48 +0000992 bool isMemThumbSPI() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000993 if (!isMemory() || Memory.OffsetRegNum != 0 ||
994 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbach23983d62011-08-19 18:13:48 +0000995 return false;
996 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +0000997 if (!Memory.OffsetImm) return true;
998 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach23983d62011-08-19 18:13:48 +0000999 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendling811c9362010-11-30 07:44:32 +00001000 }
Jim Grosbach7db8d692011-09-08 22:07:06 +00001001 bool isMemImm8s4Offset() const {
Jim Grosbach8648c102011-12-19 23:06:24 +00001002 // If we have an immediate that's not a constant, treat it as a label
1003 // reference needing a fixup. If it is a constant, it's something else
1004 // and we reject it.
1005 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
1006 return true;
Jim Grosbacha95ec992011-10-11 17:29:55 +00001007 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7db8d692011-09-08 22:07:06 +00001008 return false;
1009 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +00001010 if (!Memory.OffsetImm) return true;
1011 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7db8d692011-09-08 22:07:06 +00001012 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
1013 }
Jim Grosbacha05627e2011-09-09 18:37:27 +00001014 bool isMemImm0_1020s4Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001015 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha05627e2011-09-09 18:37:27 +00001016 return false;
1017 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +00001018 if (!Memory.OffsetImm) return true;
1019 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha05627e2011-09-09 18:37:27 +00001020 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
1021 }
Jim Grosbachd3595712011-08-03 23:50:40 +00001022 bool isMemImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001023 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachd3595712011-08-03 23:50:40 +00001024 return false;
1025 // Immediate offset in range [-255, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +00001026 if (!Memory.OffsetImm) return true;
1027 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson49168402011-09-23 22:25:02 +00001028 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbachd3595712011-08-03 23:50:40 +00001029 }
Jim Grosbach2392c532011-09-07 23:39:14 +00001030 bool isMemPosImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001031 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach2392c532011-09-07 23:39:14 +00001032 return false;
1033 // Immediate offset in range [0, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +00001034 if (!Memory.OffsetImm) return true;
1035 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2392c532011-09-07 23:39:14 +00001036 return Val >= 0 && Val < 256;
1037 }
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001038 bool isMemNegImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001039 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001040 return false;
1041 // Immediate offset in range [-255, -1].
Jim Grosbach175c7d02011-12-06 04:49:29 +00001042 if (!Memory.OffsetImm) return false;
Jim Grosbach871dff72011-10-11 15:59:20 +00001043 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach175c7d02011-12-06 04:49:29 +00001044 return (Val == INT32_MIN) || (Val > -256 && Val < 0);
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001045 }
1046 bool isMemUImm12Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001047 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001048 return false;
1049 // Immediate offset in range [0, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +00001050 if (!Memory.OffsetImm) return true;
1051 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001052 return (Val >= 0 && Val < 4096);
1053 }
Jim Grosbachd3595712011-08-03 23:50:40 +00001054 bool isMemImm12Offset() const {
Jim Grosbach95466ce2011-08-08 20:59:31 +00001055 // If we have an immediate that's not a constant, treat it as a label
1056 // reference needing a fixup. If it is a constant, it's something else
1057 // and we reject it.
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001058 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach95466ce2011-08-08 20:59:31 +00001059 return true;
1060
Jim Grosbacha95ec992011-10-11 17:29:55 +00001061 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachd3595712011-08-03 23:50:40 +00001062 return false;
1063 // Immediate offset in range [-4095, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +00001064 if (!Memory.OffsetImm) return true;
1065 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson967674d2011-08-29 19:36:44 +00001066 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbachd3595712011-08-03 23:50:40 +00001067 }
1068 bool isPostIdxImm8() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001069 if (Kind != k_Immediate)
Jim Grosbachd3595712011-08-03 23:50:40 +00001070 return false;
1071 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1072 if (!CE) return false;
1073 int64_t Val = CE->getValue();
Owen Andersonf02d98d2011-08-29 17:17:09 +00001074 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbachd3595712011-08-03 23:50:40 +00001075 }
Jim Grosbach93981412011-10-11 21:55:36 +00001076 bool isPostIdxImm8s4() const {
1077 if (Kind != k_Immediate)
1078 return false;
1079 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1080 if (!CE) return false;
1081 int64_t Val = CE->getValue();
1082 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1083 (Val == INT32_MIN);
1084 }
Jim Grosbachd3595712011-08-03 23:50:40 +00001085
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001086 bool isMSRMask() const { return Kind == k_MSRMask; }
1087 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001088
Jim Grosbach741cd732011-10-17 22:26:03 +00001089 // NEON operands.
Jim Grosbach2f50e922011-12-15 21:44:33 +00001090 bool isSingleSpacedVectorList() const {
1091 return Kind == k_VectorList && !VectorList.isDoubleSpaced;
1092 }
1093 bool isDoubleSpacedVectorList() const {
1094 return Kind == k_VectorList && VectorList.isDoubleSpaced;
1095 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001096 bool isVecListOneD() const {
Jim Grosbach2f50e922011-12-15 21:44:33 +00001097 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001098 return VectorList.Count == 1;
1099 }
1100
Jim Grosbach2f2e3c42011-10-21 18:54:25 +00001101 bool isVecListTwoD() const {
Jim Grosbach2f50e922011-12-15 21:44:33 +00001102 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach2f2e3c42011-10-21 18:54:25 +00001103 return VectorList.Count == 2;
1104 }
1105
Jim Grosbachc4360fe2011-10-21 20:02:19 +00001106 bool isVecListThreeD() const {
Jim Grosbach2f50e922011-12-15 21:44:33 +00001107 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachc4360fe2011-10-21 20:02:19 +00001108 return VectorList.Count == 3;
1109 }
1110
Jim Grosbach846bcff2011-10-21 20:35:01 +00001111 bool isVecListFourD() const {
Jim Grosbach2f50e922011-12-15 21:44:33 +00001112 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach846bcff2011-10-21 20:35:01 +00001113 return VectorList.Count == 4;
1114 }
1115
Jim Grosbach118b38c2011-10-21 22:21:10 +00001116 bool isVecListTwoQ() const {
Jim Grosbach2f50e922011-12-15 21:44:33 +00001117 if (!isDoubleSpacedVectorList()) return false;
1118 return VectorList.Count == 2;
Jim Grosbach118b38c2011-10-21 22:21:10 +00001119 }
1120
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00001121 bool isVecListOneDAllLanes() const {
1122 if (Kind != k_VectorListAllLanes) return false;
1123 return VectorList.Count == 1;
1124 }
1125
Jim Grosbach3ecf9762011-11-30 18:21:25 +00001126 bool isVecListTwoDAllLanes() const {
1127 if (Kind != k_VectorListAllLanes) return false;
1128 return VectorList.Count == 2;
1129 }
1130
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001131 bool isSingleSpacedVectorIndexed() const {
1132 return Kind == k_VectorListIndexed && !VectorList.isDoubleSpaced;
1133 }
1134 bool isDoubleSpacedVectorIndexed() const {
1135 return Kind == k_VectorListIndexed && VectorList.isDoubleSpaced;
1136 }
Jim Grosbach04945c42011-12-02 00:35:16 +00001137 bool isVecListOneDByteIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001138 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach04945c42011-12-02 00:35:16 +00001139 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1140 }
1141
Jim Grosbachda511042011-12-14 23:35:06 +00001142 bool isVecListOneDHWordIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001143 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbachda511042011-12-14 23:35:06 +00001144 return VectorList.Count == 1 && VectorList.LaneIndex <= 3;
1145 }
1146
1147 bool isVecListOneDWordIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001148 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbachda511042011-12-14 23:35:06 +00001149 return VectorList.Count == 1 && VectorList.LaneIndex <= 1;
1150 }
1151
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00001152 bool isVecListTwoDByteIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001153 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00001154 return VectorList.Count == 2 && VectorList.LaneIndex <= 7;
1155 }
1156
Jim Grosbachda511042011-12-14 23:35:06 +00001157 bool isVecListTwoDHWordIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001158 if (!isSingleSpacedVectorIndexed()) return false;
1159 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1160 }
1161
1162 bool isVecListTwoQWordIndexed() const {
1163 if (!isDoubleSpacedVectorIndexed()) return false;
1164 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1165 }
1166
1167 bool isVecListTwoQHWordIndexed() const {
1168 if (!isDoubleSpacedVectorIndexed()) return false;
Jim Grosbachda511042011-12-14 23:35:06 +00001169 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1170 }
1171
1172 bool isVecListTwoDWordIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001173 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbachda511042011-12-14 23:35:06 +00001174 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1175 }
1176
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001177 bool isVectorIndex8() const {
1178 if (Kind != k_VectorIndex) return false;
1179 return VectorIndex.Val < 8;
1180 }
1181 bool isVectorIndex16() const {
1182 if (Kind != k_VectorIndex) return false;
1183 return VectorIndex.Val < 4;
1184 }
1185 bool isVectorIndex32() const {
1186 if (Kind != k_VectorIndex) return false;
1187 return VectorIndex.Val < 2;
1188 }
1189
Jim Grosbach741cd732011-10-17 22:26:03 +00001190 bool isNEONi8splat() const {
1191 if (Kind != k_Immediate)
1192 return false;
1193 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1194 // Must be a constant.
1195 if (!CE) return false;
1196 int64_t Value = CE->getValue();
1197 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1198 // value.
Jim Grosbach741cd732011-10-17 22:26:03 +00001199 return Value >= 0 && Value < 256;
1200 }
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001201
Jim Grosbachcda32ae2011-10-17 23:09:09 +00001202 bool isNEONi16splat() const {
1203 if (Kind != k_Immediate)
1204 return false;
1205 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1206 // Must be a constant.
1207 if (!CE) return false;
1208 int64_t Value = CE->getValue();
1209 // i16 value in the range [0,255] or [0x0100, 0xff00]
1210 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1211 }
1212
Jim Grosbach8211c052011-10-18 00:22:00 +00001213 bool isNEONi32splat() const {
1214 if (Kind != k_Immediate)
1215 return false;
1216 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1217 // Must be a constant.
1218 if (!CE) return false;
1219 int64_t Value = CE->getValue();
1220 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1221 return (Value >= 0 && Value < 256) ||
1222 (Value >= 0x0100 && Value <= 0xff00) ||
1223 (Value >= 0x010000 && Value <= 0xff0000) ||
1224 (Value >= 0x01000000 && Value <= 0xff000000);
1225 }
1226
1227 bool isNEONi32vmov() const {
1228 if (Kind != k_Immediate)
1229 return false;
1230 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1231 // Must be a constant.
1232 if (!CE) return false;
1233 int64_t Value = CE->getValue();
1234 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1235 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1236 return (Value >= 0 && Value < 256) ||
1237 (Value >= 0x0100 && Value <= 0xff00) ||
1238 (Value >= 0x010000 && Value <= 0xff0000) ||
1239 (Value >= 0x01000000 && Value <= 0xff000000) ||
1240 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1241 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1242 }
Jim Grosbach045b6c72011-12-19 23:51:07 +00001243 bool isNEONi32vmovNeg() const {
1244 if (Kind != k_Immediate)
1245 return false;
1246 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1247 // Must be a constant.
1248 if (!CE) return false;
1249 int64_t Value = ~CE->getValue();
1250 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1251 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1252 return (Value >= 0 && Value < 256) ||
1253 (Value >= 0x0100 && Value <= 0xff00) ||
1254 (Value >= 0x010000 && Value <= 0xff0000) ||
1255 (Value >= 0x01000000 && Value <= 0xff000000) ||
1256 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1257 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1258 }
Jim Grosbach8211c052011-10-18 00:22:00 +00001259
Jim Grosbache4454e02011-10-18 16:18:11 +00001260 bool isNEONi64splat() const {
1261 if (Kind != k_Immediate)
1262 return false;
1263 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1264 // Must be a constant.
1265 if (!CE) return false;
1266 uint64_t Value = CE->getValue();
1267 // i64 value with each byte being either 0 or 0xff.
1268 for (unsigned i = 0; i < 8; ++i)
1269 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1270 return true;
1271 }
1272
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001273 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner5d6f6a02010-10-29 00:27:31 +00001274 // Add as immediates when possible. Null MCExpr = 0.
1275 if (Expr == 0)
1276 Inst.addOperand(MCOperand::CreateImm(0));
1277 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001278 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1279 else
1280 Inst.addOperand(MCOperand::CreateExpr(Expr));
1281 }
1282
Daniel Dunbard8042b72010-08-11 06:36:53 +00001283 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001284 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbard8042b72010-08-11 06:36:53 +00001285 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach968c9272010-12-06 18:30:57 +00001286 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1287 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbard8042b72010-08-11 06:36:53 +00001288 }
1289
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001290 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1291 assert(N == 1 && "Invalid number of operands!");
1292 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1293 }
1294
Jim Grosbach48399582011-10-12 17:34:41 +00001295 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1296 assert(N == 1 && "Invalid number of operands!");
1297 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1298 }
1299
1300 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1301 assert(N == 1 && "Invalid number of operands!");
1302 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1303 }
1304
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001305 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1306 assert(N == 1 && "Invalid number of operands!");
1307 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1308 }
1309
1310 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1311 assert(N == 1 && "Invalid number of operands!");
1312 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1313 }
1314
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001315 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1316 assert(N == 1 && "Invalid number of operands!");
1317 Inst.addOperand(MCOperand::CreateReg(getReg()));
1318 }
1319
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001320 void addRegOperands(MCInst &Inst, unsigned N) const {
1321 assert(N == 1 && "Invalid number of operands!");
1322 Inst.addOperand(MCOperand::CreateReg(getReg()));
1323 }
1324
Jim Grosbachac798e12011-07-25 20:49:51 +00001325 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001326 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001327 assert(isRegShiftedReg() &&
1328 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachac798e12011-07-25 20:49:51 +00001329 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1330 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001331 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachac798e12011-07-25 20:49:51 +00001332 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001333 }
1334
Jim Grosbachac798e12011-07-25 20:49:51 +00001335 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson04912702011-07-21 23:38:37 +00001336 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001337 assert(isRegShiftedImm() &&
1338 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachac798e12011-07-25 20:49:51 +00001339 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Andersonb595ed02011-07-21 18:54:16 +00001340 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachac798e12011-07-25 20:49:51 +00001341 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Andersonb595ed02011-07-21 18:54:16 +00001342 }
1343
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001344 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001345 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001346 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1347 ShifterImm.Imm));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001348 }
1349
Bill Wendling8d2aa032010-11-08 23:49:57 +00001350 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling2cae3272010-11-09 22:44:22 +00001351 assert(N == 1 && "Invalid number of operands!");
Bill Wendlingbed94652010-11-09 23:28:44 +00001352 const SmallVectorImpl<unsigned> &RegList = getRegList();
1353 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00001354 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1355 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling8d2aa032010-11-08 23:49:57 +00001356 }
1357
Bill Wendling9898ac92010-11-17 04:32:08 +00001358 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1359 addRegListOperands(Inst, N);
1360 }
1361
1362 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1363 addRegListOperands(Inst, N);
1364 }
1365
Jim Grosbach833b9d32011-07-27 20:15:40 +00001366 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1367 assert(N == 1 && "Invalid number of operands!");
1368 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1369 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1370 }
1371
Jim Grosbach864b6092011-07-28 21:34:26 +00001372 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1373 assert(N == 1 && "Invalid number of operands!");
1374 // Munge the lsb/width into a bitfield mask.
1375 unsigned lsb = Bitfield.LSB;
1376 unsigned width = Bitfield.Width;
1377 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1378 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1379 (32 - (lsb + width)));
1380 Inst.addOperand(MCOperand::CreateImm(Mask));
1381 }
1382
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001383 void addImmOperands(MCInst &Inst, unsigned N) const {
1384 assert(N == 1 && "Invalid number of operands!");
1385 addExpr(Inst, getImm());
1386 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00001387
Jim Grosbache7fbce72011-10-03 23:38:36 +00001388 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1389 assert(N == 1 && "Invalid number of operands!");
1390 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1391 }
1392
Jim Grosbach7db8d692011-09-08 22:07:06 +00001393 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1394 assert(N == 1 && "Invalid number of operands!");
1395 // FIXME: We really want to scale the value here, but the LDRD/STRD
1396 // instruction don't encode operands that way yet.
1397 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1398 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1399 }
1400
Jim Grosbach0a0b3072011-08-24 21:22:15 +00001401 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1402 assert(N == 1 && "Invalid number of operands!");
1403 // The immediate is scaled by four in the encoding and is stored
1404 // in the MCInst as such. Lop off the low two bits here.
1405 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1406 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1407 }
1408
1409 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1410 assert(N == 1 && "Invalid number of operands!");
1411 // The immediate is scaled by four in the encoding and is stored
1412 // in the MCInst as such. Lop off the low two bits here.
1413 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1414 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1415 }
1416
Jim Grosbach475c6db2011-07-25 23:09:14 +00001417 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1418 assert(N == 1 && "Invalid number of operands!");
1419 // The constant encodes as the immediate-1, and we store in the instruction
1420 // the bits as encoded, so subtract off one here.
1421 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1422 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1423 }
1424
Jim Grosbach801e0a32011-07-22 23:16:18 +00001425 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1426 assert(N == 1 && "Invalid number of operands!");
1427 // The constant encodes as the immediate-1, and we store in the instruction
1428 // the bits as encoded, so subtract off one here.
1429 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1430 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1431 }
1432
Jim Grosbach46dd4132011-08-17 21:51:27 +00001433 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1434 assert(N == 1 && "Invalid number of operands!");
1435 // The constant encodes as the immediate, except for 32, which encodes as
1436 // zero.
1437 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1438 unsigned Imm = CE->getValue();
1439 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1440 }
1441
Jim Grosbach27c1e252011-07-21 17:23:04 +00001442 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1443 assert(N == 1 && "Invalid number of operands!");
1444 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1445 // the instruction as well.
1446 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1447 int Val = CE->getValue();
1448 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1449 }
1450
Jim Grosbachb009a872011-10-28 22:36:30 +00001451 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1452 assert(N == 1 && "Invalid number of operands!");
1453 // The operand is actually a t2_so_imm, but we have its bitwise
1454 // negation in the assembly source, so twiddle it here.
1455 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1456 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1457 }
1458
Jim Grosbach30506252011-12-08 00:31:07 +00001459 void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1460 assert(N == 1 && "Invalid number of operands!");
1461 // The operand is actually a t2_so_imm, but we have its
1462 // negation in the assembly source, so twiddle it here.
1463 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1464 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1465 }
1466
Jim Grosbach3d785ed2011-10-28 22:50:54 +00001467 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1468 assert(N == 1 && "Invalid number of operands!");
1469 // The operand is actually a so_imm, but we have its bitwise
1470 // negation in the assembly source, so twiddle it here.
1471 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1472 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1473 }
1474
Jim Grosbach30506252011-12-08 00:31:07 +00001475 void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
1476 assert(N == 1 && "Invalid number of operands!");
1477 // The operand is actually a so_imm, but we have its
1478 // negation in the assembly source, so twiddle it here.
1479 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1480 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1481 }
1482
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001483 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1484 assert(N == 1 && "Invalid number of operands!");
1485 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1486 }
1487
Jim Grosbachd3595712011-08-03 23:50:40 +00001488 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1489 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001490 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopesf170f8b2011-03-24 21:04:58 +00001491 }
1492
Jim Grosbacha95ec992011-10-11 17:29:55 +00001493 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1494 assert(N == 2 && "Invalid number of operands!");
1495 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1496 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1497 }
1498
Jim Grosbachd3595712011-08-03 23:50:40 +00001499 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1500 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001501 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1502 if (!Memory.OffsetRegNum) {
Jim Grosbachd3595712011-08-03 23:50:40 +00001503 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1504 // Special case for #-0
1505 if (Val == INT32_MIN) Val = 0;
1506 if (Val < 0) Val = -Val;
1507 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1508 } else {
1509 // For register offset, we encode the shift type and negation flag
1510 // here.
Jim Grosbach871dff72011-10-11 15:59:20 +00001511 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1512 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001513 }
Jim Grosbach871dff72011-10-11 15:59:20 +00001514 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1515 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001516 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001517 }
1518
Jim Grosbachcd17c122011-08-04 23:01:30 +00001519 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1520 assert(N == 2 && "Invalid number of operands!");
1521 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1522 assert(CE && "non-constant AM2OffsetImm operand!");
1523 int32_t Val = CE->getValue();
1524 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1525 // Special case for #-0
1526 if (Val == INT32_MIN) Val = 0;
1527 if (Val < 0) Val = -Val;
1528 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1529 Inst.addOperand(MCOperand::CreateReg(0));
1530 Inst.addOperand(MCOperand::CreateImm(Val));
1531 }
1532
Jim Grosbach5b96b802011-08-10 20:29:19 +00001533 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1534 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach8648c102011-12-19 23:06:24 +00001535 // If we have an immediate that's not a constant, treat it as a label
1536 // reference needing a fixup. If it is a constant, it's something else
1537 // and we reject it.
1538 if (isImm()) {
1539 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1540 Inst.addOperand(MCOperand::CreateReg(0));
1541 Inst.addOperand(MCOperand::CreateImm(0));
1542 return;
1543 }
1544
Jim Grosbach871dff72011-10-11 15:59:20 +00001545 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1546 if (!Memory.OffsetRegNum) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00001547 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1548 // Special case for #-0
1549 if (Val == INT32_MIN) Val = 0;
1550 if (Val < 0) Val = -Val;
1551 Val = ARM_AM::getAM3Opc(AddSub, Val);
1552 } else {
1553 // For register offset, we encode the shift type and negation flag
1554 // here.
Jim Grosbach871dff72011-10-11 15:59:20 +00001555 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach5b96b802011-08-10 20:29:19 +00001556 }
Jim Grosbach871dff72011-10-11 15:59:20 +00001557 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1558 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach5b96b802011-08-10 20:29:19 +00001559 Inst.addOperand(MCOperand::CreateImm(Val));
1560 }
1561
1562 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1563 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001564 if (Kind == k_PostIndexRegister) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00001565 int32_t Val =
1566 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1567 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1568 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001569 return;
Jim Grosbach5b96b802011-08-10 20:29:19 +00001570 }
1571
1572 // Constant offset.
1573 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1574 int32_t Val = CE->getValue();
1575 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1576 // Special case for #-0
1577 if (Val == INT32_MIN) Val = 0;
1578 if (Val < 0) Val = -Val;
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001579 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach5b96b802011-08-10 20:29:19 +00001580 Inst.addOperand(MCOperand::CreateReg(0));
1581 Inst.addOperand(MCOperand::CreateImm(Val));
1582 }
1583
Jim Grosbachd3595712011-08-03 23:50:40 +00001584 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1585 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachfb2f1d62011-11-01 01:24:45 +00001586 // If we have an immediate that's not a constant, treat it as a label
1587 // reference needing a fixup. If it is a constant, it's something else
1588 // and we reject it.
1589 if (isImm()) {
1590 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1591 Inst.addOperand(MCOperand::CreateImm(0));
1592 return;
1593 }
1594
Jim Grosbachd3595712011-08-03 23:50:40 +00001595 // The lower two bits are always zero and as such are not encoded.
Jim Grosbach871dff72011-10-11 15:59:20 +00001596 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00001597 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1598 // Special case for #-0
1599 if (Val == INT32_MIN) Val = 0;
1600 if (Val < 0) Val = -Val;
1601 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbach871dff72011-10-11 15:59:20 +00001602 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001603 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00001604 }
1605
Jim Grosbach7db8d692011-09-08 22:07:06 +00001606 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1607 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach8648c102011-12-19 23:06:24 +00001608 // If we have an immediate that's not a constant, treat it as a label
1609 // reference needing a fixup. If it is a constant, it's something else
1610 // and we reject it.
1611 if (isImm()) {
1612 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1613 Inst.addOperand(MCOperand::CreateImm(0));
1614 return;
1615 }
1616
Jim Grosbach871dff72011-10-11 15:59:20 +00001617 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1618 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7db8d692011-09-08 22:07:06 +00001619 Inst.addOperand(MCOperand::CreateImm(Val));
1620 }
1621
Jim Grosbacha05627e2011-09-09 18:37:27 +00001622 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1623 assert(N == 2 && "Invalid number of operands!");
1624 // The lower two bits are always zero and as such are not encoded.
Jim Grosbach871dff72011-10-11 15:59:20 +00001625 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1626 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha05627e2011-09-09 18:37:27 +00001627 Inst.addOperand(MCOperand::CreateImm(Val));
1628 }
1629
Jim Grosbachd3595712011-08-03 23:50:40 +00001630 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1631 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001632 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1633 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001634 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner5d6f6a02010-10-29 00:27:31 +00001635 }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001636
Jim Grosbach2392c532011-09-07 23:39:14 +00001637 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1638 addMemImm8OffsetOperands(Inst, N);
1639 }
1640
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001641 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach2392c532011-09-07 23:39:14 +00001642 addMemImm8OffsetOperands(Inst, N);
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001643 }
1644
1645 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1646 assert(N == 2 && "Invalid number of operands!");
1647 // If this is an immediate, it's a label reference.
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001648 if (Kind == k_Immediate) {
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001649 addExpr(Inst, getImm());
1650 Inst.addOperand(MCOperand::CreateImm(0));
1651 return;
1652 }
1653
1654 // Otherwise, it's a normal memory reg+offset.
Jim Grosbach871dff72011-10-11 15:59:20 +00001655 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1656 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001657 Inst.addOperand(MCOperand::CreateImm(Val));
1658 }
1659
Jim Grosbachd3595712011-08-03 23:50:40 +00001660 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1661 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach95466ce2011-08-08 20:59:31 +00001662 // If this is an immediate, it's a label reference.
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001663 if (Kind == k_Immediate) {
Jim Grosbach95466ce2011-08-08 20:59:31 +00001664 addExpr(Inst, getImm());
1665 Inst.addOperand(MCOperand::CreateImm(0));
1666 return;
1667 }
1668
1669 // Otherwise, it's a normal memory reg+offset.
Jim Grosbach871dff72011-10-11 15:59:20 +00001670 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1671 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001672 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendling092a7bd2010-12-14 03:36:38 +00001673 }
Bill Wendling811c9362010-11-30 07:44:32 +00001674
Jim Grosbach05541f42011-09-19 22:21:13 +00001675 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1676 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001677 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1678 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach05541f42011-09-19 22:21:13 +00001679 }
1680
1681 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1682 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001683 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1684 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach05541f42011-09-19 22:21:13 +00001685 }
1686
Jim Grosbachd3595712011-08-03 23:50:40 +00001687 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1688 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001689 unsigned Val =
1690 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1691 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbach871dff72011-10-11 15:59:20 +00001692 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1693 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001694 Inst.addOperand(MCOperand::CreateImm(Val));
1695 }
1696
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001697 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1698 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001699 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1700 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1701 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001702 }
1703
Jim Grosbachd3595712011-08-03 23:50:40 +00001704 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1705 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001706 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1707 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001708 }
1709
Jim Grosbach3fe94e32011-08-19 17:55:24 +00001710 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1711 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001712 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1713 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach3fe94e32011-08-19 17:55:24 +00001714 Inst.addOperand(MCOperand::CreateImm(Val));
1715 }
1716
Jim Grosbach26d35872011-08-19 18:55:51 +00001717 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1718 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001719 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1720 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach26d35872011-08-19 18:55:51 +00001721 Inst.addOperand(MCOperand::CreateImm(Val));
1722 }
1723
Jim Grosbacha32c7532011-08-19 18:49:59 +00001724 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1725 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001726 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1727 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha32c7532011-08-19 18:49:59 +00001728 Inst.addOperand(MCOperand::CreateImm(Val));
1729 }
1730
Jim Grosbach23983d62011-08-19 18:13:48 +00001731 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1732 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001733 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1734 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach23983d62011-08-19 18:13:48 +00001735 Inst.addOperand(MCOperand::CreateImm(Val));
1736 }
1737
Jim Grosbachd3595712011-08-03 23:50:40 +00001738 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1739 assert(N == 1 && "Invalid number of operands!");
1740 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1741 assert(CE && "non-constant post-idx-imm8 operand!");
1742 int Imm = CE->getValue();
1743 bool isAdd = Imm >= 0;
Owen Andersonf02d98d2011-08-29 17:17:09 +00001744 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00001745 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1746 Inst.addOperand(MCOperand::CreateImm(Imm));
1747 }
1748
Jim Grosbach93981412011-10-11 21:55:36 +00001749 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1750 assert(N == 1 && "Invalid number of operands!");
1751 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1752 assert(CE && "non-constant post-idx-imm8s4 operand!");
1753 int Imm = CE->getValue();
1754 bool isAdd = Imm >= 0;
1755 if (Imm == INT32_MIN) Imm = 0;
1756 // Immediate is scaled by 4.
1757 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1758 Inst.addOperand(MCOperand::CreateImm(Imm));
1759 }
1760
Jim Grosbachd3595712011-08-03 23:50:40 +00001761 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1762 assert(N == 2 && "Invalid number of operands!");
1763 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachc320c852011-08-05 21:28:30 +00001764 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1765 }
1766
1767 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1768 assert(N == 2 && "Invalid number of operands!");
1769 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1770 // The sign, shift type, and shift amount are encoded in a single operand
1771 // using the AM2 encoding helpers.
1772 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1773 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1774 PostIdxReg.ShiftTy);
1775 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendling811c9362010-11-30 07:44:32 +00001776 }
1777
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001778 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1779 assert(N == 1 && "Invalid number of operands!");
1780 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1781 }
1782
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001783 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1784 assert(N == 1 && "Invalid number of operands!");
1785 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1786 }
1787
Jim Grosbach182b6a02011-11-29 23:51:09 +00001788 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001789 assert(N == 1 && "Invalid number of operands!");
1790 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1791 }
1792
Jim Grosbach04945c42011-12-02 00:35:16 +00001793 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1794 assert(N == 2 && "Invalid number of operands!");
1795 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1796 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1797 }
1798
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001799 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1800 assert(N == 1 && "Invalid number of operands!");
1801 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1802 }
1803
1804 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1805 assert(N == 1 && "Invalid number of operands!");
1806 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1807 }
1808
1809 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1810 assert(N == 1 && "Invalid number of operands!");
1811 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1812 }
1813
Jim Grosbach741cd732011-10-17 22:26:03 +00001814 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1815 assert(N == 1 && "Invalid number of operands!");
1816 // The immediate encodes the type of constant as well as the value.
1817 // Mask in that this is an i8 splat.
1818 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1819 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1820 }
1821
Jim Grosbachcda32ae2011-10-17 23:09:09 +00001822 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1823 assert(N == 1 && "Invalid number of operands!");
1824 // The immediate encodes the type of constant as well as the value.
1825 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1826 unsigned Value = CE->getValue();
1827 if (Value >= 256)
1828 Value = (Value >> 8) | 0xa00;
1829 else
1830 Value |= 0x800;
1831 Inst.addOperand(MCOperand::CreateImm(Value));
1832 }
1833
Jim Grosbach8211c052011-10-18 00:22:00 +00001834 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1835 assert(N == 1 && "Invalid number of operands!");
1836 // The immediate encodes the type of constant as well as the value.
1837 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1838 unsigned Value = CE->getValue();
1839 if (Value >= 256 && Value <= 0xff00)
1840 Value = (Value >> 8) | 0x200;
1841 else if (Value > 0xffff && Value <= 0xff0000)
1842 Value = (Value >> 16) | 0x400;
1843 else if (Value > 0xffffff)
1844 Value = (Value >> 24) | 0x600;
1845 Inst.addOperand(MCOperand::CreateImm(Value));
1846 }
1847
1848 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1849 assert(N == 1 && "Invalid number of operands!");
1850 // The immediate encodes the type of constant as well as the value.
1851 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1852 unsigned Value = CE->getValue();
1853 if (Value >= 256 && Value <= 0xffff)
1854 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1855 else if (Value > 0xffff && Value <= 0xffffff)
1856 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1857 else if (Value > 0xffffff)
1858 Value = (Value >> 24) | 0x600;
1859 Inst.addOperand(MCOperand::CreateImm(Value));
1860 }
1861
Jim Grosbach045b6c72011-12-19 23:51:07 +00001862 void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const {
1863 assert(N == 1 && "Invalid number of operands!");
1864 // The immediate encodes the type of constant as well as the value.
1865 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1866 unsigned Value = ~CE->getValue();
1867 if (Value >= 256 && Value <= 0xffff)
1868 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1869 else if (Value > 0xffff && Value <= 0xffffff)
1870 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1871 else if (Value > 0xffffff)
1872 Value = (Value >> 24) | 0x600;
1873 Inst.addOperand(MCOperand::CreateImm(Value));
1874 }
1875
Jim Grosbache4454e02011-10-18 16:18:11 +00001876 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1877 assert(N == 1 && "Invalid number of operands!");
1878 // The immediate encodes the type of constant as well as the value.
1879 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1880 uint64_t Value = CE->getValue();
1881 unsigned Imm = 0;
1882 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1883 Imm |= (Value & 1) << i;
1884 }
1885 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1886 }
1887
Jim Grosbach602aa902011-07-13 15:34:57 +00001888 virtual void print(raw_ostream &OS) const;
Daniel Dunbarebace222010-08-11 06:37:04 +00001889
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001890 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001891 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001892 Op->ITMask.Mask = Mask;
1893 Op->StartLoc = S;
1894 Op->EndLoc = S;
1895 return Op;
1896 }
1897
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001898 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001899 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001900 Op->CC.Val = CC;
1901 Op->StartLoc = S;
1902 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001903 return Op;
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001904 }
1905
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001906 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001907 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001908 Op->Cop.Val = CopVal;
1909 Op->StartLoc = S;
1910 Op->EndLoc = S;
1911 return Op;
1912 }
1913
1914 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001915 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001916 Op->Cop.Val = CopVal;
1917 Op->StartLoc = S;
1918 Op->EndLoc = S;
1919 return Op;
1920 }
1921
Jim Grosbach48399582011-10-12 17:34:41 +00001922 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1923 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1924 Op->Cop.Val = Val;
1925 Op->StartLoc = S;
1926 Op->EndLoc = E;
1927 return Op;
1928 }
1929
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001930 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001931 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001932 Op->Reg.RegNum = RegNum;
1933 Op->StartLoc = S;
1934 Op->EndLoc = S;
1935 return Op;
1936 }
1937
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001938 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001939 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001940 Op->Tok.Data = Str.data();
1941 Op->Tok.Length = Str.size();
1942 Op->StartLoc = S;
1943 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001944 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001945 }
1946
Bill Wendling2063b842010-11-18 23:43:05 +00001947 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001948 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001949 Op->Reg.RegNum = RegNum;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001950 Op->StartLoc = S;
1951 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001952 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001953 }
1954
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001955 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1956 unsigned SrcReg,
1957 unsigned ShiftReg,
1958 unsigned ShiftImm,
1959 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001960 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachac798e12011-07-25 20:49:51 +00001961 Op->RegShiftedReg.ShiftTy = ShTy;
1962 Op->RegShiftedReg.SrcReg = SrcReg;
1963 Op->RegShiftedReg.ShiftReg = ShiftReg;
1964 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001965 Op->StartLoc = S;
1966 Op->EndLoc = E;
1967 return Op;
1968 }
1969
Owen Andersonb595ed02011-07-21 18:54:16 +00001970 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1971 unsigned SrcReg,
1972 unsigned ShiftImm,
1973 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001974 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachac798e12011-07-25 20:49:51 +00001975 Op->RegShiftedImm.ShiftTy = ShTy;
1976 Op->RegShiftedImm.SrcReg = SrcReg;
1977 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Andersonb595ed02011-07-21 18:54:16 +00001978 Op->StartLoc = S;
1979 Op->EndLoc = E;
1980 return Op;
1981 }
1982
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001983 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001984 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001985 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001986 Op->ShifterImm.isASR = isASR;
1987 Op->ShifterImm.Imm = Imm;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001988 Op->StartLoc = S;
1989 Op->EndLoc = E;
1990 return Op;
1991 }
1992
Jim Grosbach833b9d32011-07-27 20:15:40 +00001993 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001994 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach833b9d32011-07-27 20:15:40 +00001995 Op->RotImm.Imm = Imm;
1996 Op->StartLoc = S;
1997 Op->EndLoc = E;
1998 return Op;
1999 }
2000
Jim Grosbach864b6092011-07-28 21:34:26 +00002001 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
2002 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002003 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach864b6092011-07-28 21:34:26 +00002004 Op->Bitfield.LSB = LSB;
2005 Op->Bitfield.Width = Width;
2006 Op->StartLoc = S;
2007 Op->EndLoc = E;
2008 return Op;
2009 }
2010
Bill Wendling2cae3272010-11-09 22:44:22 +00002011 static ARMOperand *
Bill Wendlingbed94652010-11-09 23:28:44 +00002012 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00002013 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002014 KindTy Kind = k_RegisterList;
Bill Wendling9898ac92010-11-17 04:32:08 +00002015
Jim Grosbach75461af2011-09-13 22:56:44 +00002016 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002017 Kind = k_DPRRegisterList;
Jim Grosbach75461af2011-09-13 22:56:44 +00002018 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng9eec7642011-07-25 21:32:49 +00002019 contains(Regs.front().first))
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002020 Kind = k_SPRRegisterList;
Bill Wendling9898ac92010-11-17 04:32:08 +00002021
2022 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendlingbed94652010-11-09 23:28:44 +00002023 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00002024 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling0ab0f672010-11-18 21:50:54 +00002025 Op->Registers.push_back(I->first);
Bill Wendling20b5ea982010-11-19 00:38:19 +00002026 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00002027 Op->StartLoc = StartLoc;
2028 Op->EndLoc = EndLoc;
Bill Wendling7cef4472010-11-06 19:56:04 +00002029 return Op;
2030 }
2031
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002032 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
Jim Grosbach2f50e922011-12-15 21:44:33 +00002033 bool isDoubleSpaced, SMLoc S, SMLoc E) {
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002034 ARMOperand *Op = new ARMOperand(k_VectorList);
2035 Op->VectorList.RegNum = RegNum;
2036 Op->VectorList.Count = Count;
Jim Grosbach2f50e922011-12-15 21:44:33 +00002037 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002038 Op->StartLoc = S;
2039 Op->EndLoc = E;
2040 return Op;
2041 }
2042
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002043 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
2044 SMLoc S, SMLoc E) {
2045 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
2046 Op->VectorList.RegNum = RegNum;
2047 Op->VectorList.Count = Count;
2048 Op->StartLoc = S;
2049 Op->EndLoc = E;
2050 return Op;
2051 }
2052
Jim Grosbach04945c42011-12-02 00:35:16 +00002053 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
Jim Grosbach75e2ab52011-12-20 19:21:26 +00002054 unsigned Index,
2055 bool isDoubleSpaced,
2056 SMLoc S, SMLoc E) {
Jim Grosbach04945c42011-12-02 00:35:16 +00002057 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
2058 Op->VectorList.RegNum = RegNum;
2059 Op->VectorList.Count = Count;
2060 Op->VectorList.LaneIndex = Index;
Jim Grosbach75e2ab52011-12-20 19:21:26 +00002061 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach04945c42011-12-02 00:35:16 +00002062 Op->StartLoc = S;
2063 Op->EndLoc = E;
2064 return Op;
2065 }
2066
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002067 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
2068 MCContext &Ctx) {
2069 ARMOperand *Op = new ARMOperand(k_VectorIndex);
2070 Op->VectorIndex.Val = Idx;
2071 Op->StartLoc = S;
2072 Op->EndLoc = E;
2073 return Op;
2074 }
2075
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002076 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002077 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002078 Op->Imm.Val = Val;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002079 Op->StartLoc = S;
2080 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002081 return Op;
Kevin Enderbyf5079942009-10-13 22:19:02 +00002082 }
2083
Jim Grosbache7fbce72011-10-03 23:38:36 +00002084 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002085 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbache7fbce72011-10-03 23:38:36 +00002086 Op->FPImm.Val = Val;
2087 Op->StartLoc = S;
2088 Op->EndLoc = S;
2089 return Op;
2090 }
2091
Jim Grosbachd3595712011-08-03 23:50:40 +00002092 static ARMOperand *CreateMem(unsigned BaseRegNum,
2093 const MCConstantExpr *OffsetImm,
2094 unsigned OffsetRegNum,
2095 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00002096 unsigned ShiftImm,
Jim Grosbacha95ec992011-10-11 17:29:55 +00002097 unsigned Alignment,
Jim Grosbachd3595712011-08-03 23:50:40 +00002098 bool isNegative,
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002099 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002100 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbach871dff72011-10-11 15:59:20 +00002101 Op->Memory.BaseRegNum = BaseRegNum;
2102 Op->Memory.OffsetImm = OffsetImm;
2103 Op->Memory.OffsetRegNum = OffsetRegNum;
2104 Op->Memory.ShiftType = ShiftType;
2105 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbacha95ec992011-10-11 17:29:55 +00002106 Op->Memory.Alignment = Alignment;
Jim Grosbach871dff72011-10-11 15:59:20 +00002107 Op->Memory.isNegative = isNegative;
Jim Grosbachd3595712011-08-03 23:50:40 +00002108 Op->StartLoc = S;
2109 Op->EndLoc = E;
2110 return Op;
2111 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00002112
Jim Grosbachc320c852011-08-05 21:28:30 +00002113 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
2114 ARM_AM::ShiftOpc ShiftTy,
2115 unsigned ShiftImm,
Jim Grosbachd3595712011-08-03 23:50:40 +00002116 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002117 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbachd3595712011-08-03 23:50:40 +00002118 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachc320c852011-08-05 21:28:30 +00002119 Op->PostIdxReg.isAdd = isAdd;
2120 Op->PostIdxReg.ShiftTy = ShiftTy;
2121 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002122 Op->StartLoc = S;
2123 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002124 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002125 }
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002126
2127 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002128 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002129 Op->MBOpt.Val = Opt;
2130 Op->StartLoc = S;
2131 Op->EndLoc = S;
2132 return Op;
2133 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002134
2135 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002136 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002137 Op->IFlags.Val = IFlags;
2138 Op->StartLoc = S;
2139 Op->EndLoc = S;
2140 return Op;
2141 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002142
2143 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002144 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002145 Op->MMask.Val = MMask;
2146 Op->StartLoc = S;
2147 Op->EndLoc = S;
2148 return Op;
2149 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002150};
2151
2152} // end anonymous namespace.
2153
Jim Grosbach602aa902011-07-13 15:34:57 +00002154void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002155 switch (Kind) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002156 case k_FPImmediate:
Jim Grosbache7fbce72011-10-03 23:38:36 +00002157 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
2158 << ") >";
2159 break;
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) {
2328 // Check for aliases registered via .req.
2329 StringMap<unsigned>::const_iterator Entry =
2330 RegisterReqs.find(Tok.getIdentifier());
2331 // If no match, return failure.
2332 if (Entry == RegisterReqs.end())
2333 return -1;
2334 Parser.Lex(); // Eat identifier token.
2335 return Entry->getValue();
2336 }
Bob Wilsonfb0bd042011-02-03 21:46:10 +00002337
Chris Lattner44e5981c2010-10-30 04:09:10 +00002338 Parser.Lex(); // Eat identifier token.
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002339
Chris Lattner44e5981c2010-10-30 04:09:10 +00002340 return RegNum;
2341}
Jim Grosbach99710a82010-11-01 16:44:21 +00002342
Jim Grosbachbb24c592011-07-13 18:49:30 +00002343// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2344// If a recoverable error occurs, return 1. If an irrecoverable error
2345// occurs, return -1. An irrecoverable error is one where tokens have been
2346// consumed in the process of trying to parse the shifter (i.e., when it is
2347// indeed a shifter operand, but malformed).
Jim Grosbach0d6022d2011-07-26 20:41:24 +00002348int ARMAsmParser::tryParseShiftRegister(
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002349 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2350 SMLoc S = Parser.getTok().getLoc();
2351 const AsmToken &Tok = Parser.getTok();
2352 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2353
Benjamin Kramer20baffb2011-11-06 20:37:06 +00002354 std::string lowerCase = Tok.getString().lower();
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002355 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbach3b559ff2011-12-07 23:40:58 +00002356 .Case("asl", ARM_AM::lsl)
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002357 .Case("lsl", ARM_AM::lsl)
2358 .Case("lsr", ARM_AM::lsr)
2359 .Case("asr", ARM_AM::asr)
2360 .Case("ror", ARM_AM::ror)
2361 .Case("rrx", ARM_AM::rrx)
2362 .Default(ARM_AM::no_shift);
2363
2364 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbachbb24c592011-07-13 18:49:30 +00002365 return 1;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002366
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002367 Parser.Lex(); // Eat the operator.
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002368
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002369 // The source register for the shift has already been added to the
2370 // operand list, so we need to pop it off and combine it into the shifted
2371 // register operand instead.
Benjamin Kramer1757e7a2011-07-14 18:41:22 +00002372 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002373 if (!PrevOp->isReg())
2374 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2375 int SrcReg = PrevOp->getReg();
2376 int64_t Imm = 0;
2377 int ShiftReg = 0;
2378 if (ShiftTy == ARM_AM::rrx) {
2379 // RRX Doesn't have an explicit shift amount. The encoder expects
2380 // the shift register to be the same as the source register. Seems odd,
2381 // but OK.
2382 ShiftReg = SrcReg;
2383 } else {
2384 // Figure out if this is shifted by a constant or a register (for non-RRX).
Jim Grosbachef70e9b2011-12-09 22:25:03 +00002385 if (Parser.getTok().is(AsmToken::Hash) ||
2386 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002387 Parser.Lex(); // Eat hash.
2388 SMLoc ImmLoc = Parser.getTok().getLoc();
2389 const MCExpr *ShiftExpr = 0;
Jim Grosbachbb24c592011-07-13 18:49:30 +00002390 if (getParser().ParseExpression(ShiftExpr)) {
2391 Error(ImmLoc, "invalid immediate shift value");
2392 return -1;
2393 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002394 // The expression must be evaluatable as an immediate.
2395 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbachbb24c592011-07-13 18:49:30 +00002396 if (!CE) {
2397 Error(ImmLoc, "invalid immediate shift value");
2398 return -1;
2399 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002400 // Range check the immediate.
2401 // lsl, ror: 0 <= imm <= 31
2402 // lsr, asr: 0 <= imm <= 32
2403 Imm = CE->getValue();
2404 if (Imm < 0 ||
2405 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2406 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbachbb24c592011-07-13 18:49:30 +00002407 Error(ImmLoc, "immediate shift value out of range");
2408 return -1;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002409 }
2410 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002411 ShiftReg = tryParseRegister();
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002412 SMLoc L = Parser.getTok().getLoc();
Jim Grosbachbb24c592011-07-13 18:49:30 +00002413 if (ShiftReg == -1) {
2414 Error (L, "expected immediate or register in shift operand");
2415 return -1;
2416 }
2417 } else {
2418 Error (Parser.getTok().getLoc(),
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002419 "expected immediate or register in shift operand");
Jim Grosbachbb24c592011-07-13 18:49:30 +00002420 return -1;
2421 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002422 }
2423
Owen Andersonb595ed02011-07-21 18:54:16 +00002424 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2425 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachac798e12011-07-25 20:49:51 +00002426 ShiftReg, Imm,
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002427 S, Parser.getTok().getLoc()));
Owen Andersonb595ed02011-07-21 18:54:16 +00002428 else
2429 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2430 S, Parser.getTok().getLoc()));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002431
Jim Grosbachbb24c592011-07-13 18:49:30 +00002432 return 0;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002433}
2434
2435
Bill Wendling2063b842010-11-18 23:43:05 +00002436/// Try to parse a register name. The token must be an Identifier when called.
2437/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2438/// if there is a "writeback". 'true' if it's not a register.
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002439///
Kevin Enderby8be42bd2009-10-30 22:55:57 +00002440/// TODO this is likely to change to allow different register types and or to
2441/// parse for a specific register type.
Bill Wendling2063b842010-11-18 23:43:05 +00002442bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002443tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattner44e5981c2010-10-30 04:09:10 +00002444 SMLoc S = Parser.getTok().getLoc();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002445 int RegNo = tryParseRegister();
Bill Wendlinge18980a2010-11-06 22:36:58 +00002446 if (RegNo == -1)
Bill Wendling2063b842010-11-18 23:43:05 +00002447 return true;
Jim Grosbach99710a82010-11-01 16:44:21 +00002448
Bill Wendling2063b842010-11-18 23:43:05 +00002449 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002450
Chris Lattner44e5981c2010-10-30 04:09:10 +00002451 const AsmToken &ExclaimTok = Parser.getTok();
2452 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling2063b842010-11-18 23:43:05 +00002453 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2454 ExclaimTok.getLoc()));
Chris Lattner44e5981c2010-10-30 04:09:10 +00002455 Parser.Lex(); // Eat exclaim token
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002456 return false;
2457 }
2458
2459 // Also check for an index operand. This is only legal for vector registers,
2460 // but that'll get caught OK in operand matching, so we don't need to
2461 // explicitly filter everything else out here.
2462 if (Parser.getTok().is(AsmToken::LBrac)) {
2463 SMLoc SIdx = Parser.getTok().getLoc();
2464 Parser.Lex(); // Eat left bracket token.
2465
2466 const MCExpr *ImmVal;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002467 if (getParser().ParseExpression(ImmVal))
2468 return MatchOperand_ParseFail;
2469 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2470 if (!MCE) {
2471 TokError("immediate value expected for vector index");
2472 return MatchOperand_ParseFail;
2473 }
2474
2475 SMLoc E = Parser.getTok().getLoc();
2476 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2477 Error(E, "']' expected");
2478 return MatchOperand_ParseFail;
2479 }
2480
2481 Parser.Lex(); // Eat right bracket token.
2482
2483 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2484 SIdx, E,
2485 getContext()));
Kevin Enderby2207e5f2009-10-07 18:01:35 +00002486 }
2487
Bill Wendling2063b842010-11-18 23:43:05 +00002488 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002489}
2490
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002491/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2492/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2493/// "c5", ...
2494static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002495 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2496 // but efficient.
2497 switch (Name.size()) {
2498 default: break;
2499 case 2:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002500 if (Name[0] != CoprocOp)
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002501 return -1;
2502 switch (Name[1]) {
2503 default: return -1;
2504 case '0': return 0;
2505 case '1': return 1;
2506 case '2': return 2;
2507 case '3': return 3;
2508 case '4': return 4;
2509 case '5': return 5;
2510 case '6': return 6;
2511 case '7': return 7;
2512 case '8': return 8;
2513 case '9': return 9;
2514 }
2515 break;
2516 case 3:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002517 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002518 return -1;
2519 switch (Name[2]) {
2520 default: return -1;
2521 case '0': return 10;
2522 case '1': return 11;
2523 case '2': return 12;
2524 case '3': return 13;
2525 case '4': return 14;
2526 case '5': return 15;
2527 }
2528 break;
2529 }
2530
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002531 return -1;
2532}
2533
Jim Grosbach3d1eac82011-08-26 21:43:41 +00002534/// parseITCondCode - Try to parse a condition code for an IT instruction.
2535ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2536parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2537 SMLoc S = Parser.getTok().getLoc();
2538 const AsmToken &Tok = Parser.getTok();
2539 if (!Tok.is(AsmToken::Identifier))
2540 return MatchOperand_NoMatch;
2541 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2542 .Case("eq", ARMCC::EQ)
2543 .Case("ne", ARMCC::NE)
2544 .Case("hs", ARMCC::HS)
2545 .Case("cs", ARMCC::HS)
2546 .Case("lo", ARMCC::LO)
2547 .Case("cc", ARMCC::LO)
2548 .Case("mi", ARMCC::MI)
2549 .Case("pl", ARMCC::PL)
2550 .Case("vs", ARMCC::VS)
2551 .Case("vc", ARMCC::VC)
2552 .Case("hi", ARMCC::HI)
2553 .Case("ls", ARMCC::LS)
2554 .Case("ge", ARMCC::GE)
2555 .Case("lt", ARMCC::LT)
2556 .Case("gt", ARMCC::GT)
2557 .Case("le", ARMCC::LE)
2558 .Case("al", ARMCC::AL)
2559 .Default(~0U);
2560 if (CC == ~0U)
2561 return MatchOperand_NoMatch;
2562 Parser.Lex(); // Eat the token.
2563
2564 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2565
2566 return MatchOperand_Success;
2567}
2568
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002569/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002570/// token must be an Identifier when called, and if it is a coprocessor
2571/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002572ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002573parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002574 SMLoc S = Parser.getTok().getLoc();
2575 const AsmToken &Tok = Parser.getTok();
Jim Grosbach54a20ed2011-10-12 20:54:17 +00002576 if (Tok.isNot(AsmToken::Identifier))
2577 return MatchOperand_NoMatch;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002578
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002579 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002580 if (Num == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002581 return MatchOperand_NoMatch;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002582
2583 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002584 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002585 return MatchOperand_Success;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002586}
2587
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002588/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002589/// token must be an Identifier when called, and if it is a coprocessor
2590/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002591ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002592parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002593 SMLoc S = Parser.getTok().getLoc();
2594 const AsmToken &Tok = Parser.getTok();
Jim Grosbach54a20ed2011-10-12 20:54:17 +00002595 if (Tok.isNot(AsmToken::Identifier))
2596 return MatchOperand_NoMatch;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002597
2598 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2599 if (Reg == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002600 return MatchOperand_NoMatch;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002601
2602 Parser.Lex(); // Eat identifier token.
2603 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002604 return MatchOperand_Success;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002605}
2606
Jim Grosbach48399582011-10-12 17:34:41 +00002607/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2608/// coproc_option : '{' imm0_255 '}'
2609ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2610parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2611 SMLoc S = Parser.getTok().getLoc();
2612
2613 // If this isn't a '{', this isn't a coprocessor immediate operand.
2614 if (Parser.getTok().isNot(AsmToken::LCurly))
2615 return MatchOperand_NoMatch;
2616 Parser.Lex(); // Eat the '{'
2617
2618 const MCExpr *Expr;
2619 SMLoc Loc = Parser.getTok().getLoc();
2620 if (getParser().ParseExpression(Expr)) {
2621 Error(Loc, "illegal expression");
2622 return MatchOperand_ParseFail;
2623 }
2624 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2625 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2626 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2627 return MatchOperand_ParseFail;
2628 }
2629 int Val = CE->getValue();
2630
2631 // Check for and consume the closing '}'
2632 if (Parser.getTok().isNot(AsmToken::RCurly))
2633 return MatchOperand_ParseFail;
2634 SMLoc E = Parser.getTok().getLoc();
2635 Parser.Lex(); // Eat the '}'
2636
2637 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2638 return MatchOperand_Success;
2639}
2640
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002641// For register list parsing, we need to map from raw GPR register numbering
2642// to the enumeration values. The enumeration values aren't sorted by
2643// register number due to our using "sp", "lr" and "pc" as canonical names.
2644static unsigned getNextRegister(unsigned Reg) {
2645 // If this is a GPR, we need to do it manually, otherwise we can rely
2646 // on the sort ordering of the enumeration since the other reg-classes
2647 // are sane.
2648 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2649 return Reg + 1;
2650 switch(Reg) {
2651 default: assert(0 && "Invalid GPR number!");
2652 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2653 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2654 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2655 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2656 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2657 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2658 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2659 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2660 }
2661}
2662
Jim Grosbach85a23432011-11-11 21:27:40 +00002663// Return the low-subreg of a given Q register.
2664static unsigned getDRegFromQReg(unsigned QReg) {
2665 switch (QReg) {
2666 default: llvm_unreachable("expected a Q register!");
2667 case ARM::Q0: return ARM::D0;
2668 case ARM::Q1: return ARM::D2;
2669 case ARM::Q2: return ARM::D4;
2670 case ARM::Q3: return ARM::D6;
2671 case ARM::Q4: return ARM::D8;
2672 case ARM::Q5: return ARM::D10;
2673 case ARM::Q6: return ARM::D12;
2674 case ARM::Q7: return ARM::D14;
2675 case ARM::Q8: return ARM::D16;
Jim Grosbacha92a5d82011-11-15 21:01:30 +00002676 case ARM::Q9: return ARM::D18;
Jim Grosbach85a23432011-11-11 21:27:40 +00002677 case ARM::Q10: return ARM::D20;
2678 case ARM::Q11: return ARM::D22;
2679 case ARM::Q12: return ARM::D24;
2680 case ARM::Q13: return ARM::D26;
2681 case ARM::Q14: return ARM::D28;
2682 case ARM::Q15: return ARM::D30;
2683 }
2684}
2685
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002686/// Parse a register list.
Bill Wendling2063b842010-11-18 23:43:05 +00002687bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002688parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan936b0d32010-01-19 21:44:56 +00002689 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00002690 "Token is not a Left Curly Brace");
Bill Wendlinge18980a2010-11-06 22:36:58 +00002691 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002692 Parser.Lex(); // Eat '{' token.
2693 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbya2b99102009-10-09 21:12:28 +00002694
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002695 // Check the first register in the list to see what register class
2696 // this is a list of.
2697 int Reg = tryParseRegister();
2698 if (Reg == -1)
2699 return Error(RegLoc, "register expected");
2700
Jim Grosbach85a23432011-11-11 21:27:40 +00002701 // The reglist instructions have at most 16 registers, so reserve
2702 // space for that many.
2703 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2704
2705 // Allow Q regs and just interpret them as the two D sub-registers.
2706 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2707 Reg = getDRegFromQReg(Reg);
2708 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2709 ++Reg;
2710 }
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00002711 const MCRegisterClass *RC;
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002712 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2713 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2714 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2715 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2716 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2717 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2718 else
2719 return Error(RegLoc, "invalid register in register list");
2720
Jim Grosbach85a23432011-11-11 21:27:40 +00002721 // Store the register.
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002722 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbya2b99102009-10-09 21:12:28 +00002723
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002724 // This starts immediately after the first register token in the list,
2725 // so we can see either a comma or a minus (range separator) as a legal
2726 // next token.
2727 while (Parser.getTok().is(AsmToken::Comma) ||
2728 Parser.getTok().is(AsmToken::Minus)) {
2729 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache891fe82011-11-15 23:19:15 +00002730 Parser.Lex(); // Eat the minus.
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002731 SMLoc EndLoc = Parser.getTok().getLoc();
2732 int EndReg = tryParseRegister();
2733 if (EndReg == -1)
2734 return Error(EndLoc, "register expected");
Jim Grosbach85a23432011-11-11 21:27:40 +00002735 // Allow Q regs and just interpret them as the two D sub-registers.
2736 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2737 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002738 // If the register is the same as the start reg, there's nothing
2739 // more to do.
2740 if (Reg == EndReg)
2741 continue;
2742 // The register must be in the same register class as the first.
2743 if (!RC->contains(EndReg))
2744 return Error(EndLoc, "invalid register in register list");
2745 // Ranges must go from low to high.
2746 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2747 return Error(EndLoc, "bad range in register list");
Kevin Enderbya2b99102009-10-09 21:12:28 +00002748
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002749 // Add all the registers in the range to the register list.
2750 while (Reg != EndReg) {
2751 Reg = getNextRegister(Reg);
2752 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2753 }
2754 continue;
2755 }
2756 Parser.Lex(); // Eat the comma.
2757 RegLoc = Parser.getTok().getLoc();
2758 int OldReg = Reg;
Jim Grosbach98bc7972011-12-08 21:34:20 +00002759 const AsmToken RegTok = Parser.getTok();
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002760 Reg = tryParseRegister();
2761 if (Reg == -1)
Jim Grosbach3337e392011-09-12 23:36:42 +00002762 return Error(RegLoc, "register expected");
Jim Grosbach85a23432011-11-11 21:27:40 +00002763 // Allow Q regs and just interpret them as the two D sub-registers.
2764 bool isQReg = false;
2765 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2766 Reg = getDRegFromQReg(Reg);
2767 isQReg = true;
2768 }
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002769 // The register must be in the same register class as the first.
2770 if (!RC->contains(Reg))
2771 return Error(RegLoc, "invalid register in register list");
2772 // List must be monotonically increasing.
Jim Grosbach98bc7972011-12-08 21:34:20 +00002773 if (getARMRegisterNumbering(Reg) < getARMRegisterNumbering(OldReg))
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002774 return Error(RegLoc, "register list not in ascending order");
Jim Grosbach98bc7972011-12-08 21:34:20 +00002775 if (getARMRegisterNumbering(Reg) == getARMRegisterNumbering(OldReg)) {
2776 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
2777 ") in register list");
2778 continue;
2779 }
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002780 // VFP register lists must also be contiguous.
2781 // It's OK to use the enumeration values directly here rather, as the
2782 // VFP register classes have the enum sorted properly.
2783 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2784 Reg != OldReg + 1)
2785 return Error(RegLoc, "non-contiguous register range");
2786 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbach85a23432011-11-11 21:27:40 +00002787 if (isQReg)
2788 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge18980a2010-11-06 22:36:58 +00002789 }
2790
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002791 SMLoc E = Parser.getTok().getLoc();
2792 if (Parser.getTok().isNot(AsmToken::RCurly))
2793 return Error(E, "'}' expected");
2794 Parser.Lex(); // Eat '}' token.
2795
Jim Grosbach18bf3632011-12-13 21:48:29 +00002796 // Push the register list operand.
Bill Wendling2063b842010-11-18 23:43:05 +00002797 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
Jim Grosbach18bf3632011-12-13 21:48:29 +00002798
2799 // The ARM system instruction variants for LDM/STM have a '^' token here.
2800 if (Parser.getTok().is(AsmToken::Caret)) {
2801 Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
2802 Parser.Lex(); // Eat '^' token.
2803 }
2804
Bill Wendling2063b842010-11-18 23:43:05 +00002805 return false;
Kevin Enderbya2b99102009-10-09 21:12:28 +00002806}
2807
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002808// Helper function to parse the lane index for vector lists.
2809ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach04945c42011-12-02 00:35:16 +00002810parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2811 Index = 0; // Always return a defined index value.
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002812 if (Parser.getTok().is(AsmToken::LBrac)) {
2813 Parser.Lex(); // Eat the '['.
2814 if (Parser.getTok().is(AsmToken::RBrac)) {
2815 // "Dn[]" is the 'all lanes' syntax.
2816 LaneKind = AllLanes;
2817 Parser.Lex(); // Eat the ']'.
2818 return MatchOperand_Success;
2819 }
Jim Grosbach04945c42011-12-02 00:35:16 +00002820 if (Parser.getTok().is(AsmToken::Integer)) {
2821 int64_t Val = Parser.getTok().getIntVal();
2822 // Make this range check context sensitive for .8, .16, .32.
2823 if (Val < 0 && Val > 7)
2824 Error(Parser.getTok().getLoc(), "lane index out of range");
2825 Index = Val;
2826 LaneKind = IndexedLane;
2827 Parser.Lex(); // Eat the token;
2828 if (Parser.getTok().isNot(AsmToken::RBrac))
2829 Error(Parser.getTok().getLoc(), "']' expected");
2830 Parser.Lex(); // Eat the ']'.
2831 return MatchOperand_Success;
2832 }
2833 Error(Parser.getTok().getLoc(), "lane index must be empty or an integer");
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002834 return MatchOperand_ParseFail;
2835 }
2836 LaneKind = NoLanes;
2837 return MatchOperand_Success;
2838}
2839
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002840// parse a vector register list
2841ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2842parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002843 VectorLaneTy LaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00002844 unsigned LaneIndex;
Jim Grosbach8d579232011-11-15 21:45:55 +00002845 SMLoc S = Parser.getTok().getLoc();
2846 // As an extension (to match gas), support a plain D register or Q register
2847 // (without encosing curly braces) as a single or double entry list,
2848 // respectively.
2849 if (Parser.getTok().is(AsmToken::Identifier)) {
2850 int Reg = tryParseRegister();
2851 if (Reg == -1)
2852 return MatchOperand_NoMatch;
2853 SMLoc E = Parser.getTok().getLoc();
2854 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach04945c42011-12-02 00:35:16 +00002855 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002856 if (Res != MatchOperand_Success)
2857 return Res;
2858 switch (LaneKind) {
2859 default:
2860 assert(0 && "unexpected lane kind!");
2861 case NoLanes:
2862 E = Parser.getTok().getLoc();
Jim Grosbach2f50e922011-12-15 21:44:33 +00002863 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002864 break;
2865 case AllLanes:
2866 E = Parser.getTok().getLoc();
2867 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, S, E));
2868 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00002869 case IndexedLane:
2870 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
Jim Grosbach75e2ab52011-12-20 19:21:26 +00002871 LaneIndex,
2872 false, S, E));
Jim Grosbach04945c42011-12-02 00:35:16 +00002873 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002874 }
Jim Grosbach8d579232011-11-15 21:45:55 +00002875 return MatchOperand_Success;
2876 }
2877 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2878 Reg = getDRegFromQReg(Reg);
Jim Grosbach04945c42011-12-02 00:35:16 +00002879 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002880 if (Res != MatchOperand_Success)
2881 return Res;
2882 switch (LaneKind) {
2883 default:
2884 assert(0 && "unexpected lane kind!");
2885 case NoLanes:
2886 E = Parser.getTok().getLoc();
Jim Grosbach2f50e922011-12-15 21:44:33 +00002887 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002888 break;
2889 case AllLanes:
2890 E = Parser.getTok().getLoc();
2891 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, S, E));
2892 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00002893 case IndexedLane:
2894 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
Jim Grosbach75e2ab52011-12-20 19:21:26 +00002895 LaneIndex,
2896 false, S, E));
Jim Grosbach04945c42011-12-02 00:35:16 +00002897 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002898 }
Jim Grosbach8d579232011-11-15 21:45:55 +00002899 return MatchOperand_Success;
2900 }
2901 Error(S, "vector register expected");
2902 return MatchOperand_ParseFail;
2903 }
2904
2905 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002906 return MatchOperand_NoMatch;
2907
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002908 Parser.Lex(); // Eat '{' token.
2909 SMLoc RegLoc = Parser.getTok().getLoc();
2910
2911 int Reg = tryParseRegister();
2912 if (Reg == -1) {
2913 Error(RegLoc, "register expected");
2914 return MatchOperand_ParseFail;
2915 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002916 unsigned Count = 1;
Jim Grosbachc2f16a32011-12-15 21:54:55 +00002917 int Spacing = 0;
Jim Grosbach080a4992011-10-28 00:06:50 +00002918 unsigned FirstReg = Reg;
2919 // The list is of D registers, but we also allow Q regs and just interpret
2920 // them as the two D sub-registers.
2921 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2922 FirstReg = Reg = getDRegFromQReg(Reg);
Jim Grosbach2f50e922011-12-15 21:44:33 +00002923 Spacing = 1; // double-spacing requires explicit D registers, otherwise
2924 // it's ambiguous with four-register single spaced.
Jim Grosbach080a4992011-10-28 00:06:50 +00002925 ++Reg;
2926 ++Count;
2927 }
Jim Grosbach04945c42011-12-02 00:35:16 +00002928 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002929 return MatchOperand_ParseFail;
Jim Grosbach080a4992011-10-28 00:06:50 +00002930
Jim Grosbache891fe82011-11-15 23:19:15 +00002931 while (Parser.getTok().is(AsmToken::Comma) ||
2932 Parser.getTok().is(AsmToken::Minus)) {
2933 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbach2f50e922011-12-15 21:44:33 +00002934 if (!Spacing)
2935 Spacing = 1; // Register range implies a single spaced list.
2936 else if (Spacing == 2) {
2937 Error(Parser.getTok().getLoc(),
2938 "sequential registers in double spaced list");
2939 return MatchOperand_ParseFail;
2940 }
Jim Grosbache891fe82011-11-15 23:19:15 +00002941 Parser.Lex(); // Eat the minus.
2942 SMLoc EndLoc = Parser.getTok().getLoc();
2943 int EndReg = tryParseRegister();
2944 if (EndReg == -1) {
2945 Error(EndLoc, "register expected");
2946 return MatchOperand_ParseFail;
2947 }
2948 // Allow Q regs and just interpret them as the two D sub-registers.
2949 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2950 EndReg = getDRegFromQReg(EndReg) + 1;
2951 // If the register is the same as the start reg, there's nothing
2952 // more to do.
2953 if (Reg == EndReg)
2954 continue;
2955 // The register must be in the same register class as the first.
2956 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
2957 Error(EndLoc, "invalid register in register list");
2958 return MatchOperand_ParseFail;
2959 }
2960 // Ranges must go from low to high.
2961 if (Reg > EndReg) {
2962 Error(EndLoc, "bad range in register list");
2963 return MatchOperand_ParseFail;
2964 }
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002965 // Parse the lane specifier if present.
2966 VectorLaneTy NextLaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00002967 unsigned NextLaneIndex;
2968 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002969 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00002970 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002971 Error(EndLoc, "mismatched lane index in register list");
2972 return MatchOperand_ParseFail;
2973 }
2974 EndLoc = Parser.getTok().getLoc();
Jim Grosbache891fe82011-11-15 23:19:15 +00002975
2976 // Add all the registers in the range to the register list.
2977 Count += EndReg - Reg;
2978 Reg = EndReg;
2979 continue;
2980 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002981 Parser.Lex(); // Eat the comma.
2982 RegLoc = Parser.getTok().getLoc();
2983 int OldReg = Reg;
2984 Reg = tryParseRegister();
2985 if (Reg == -1) {
2986 Error(RegLoc, "register expected");
2987 return MatchOperand_ParseFail;
2988 }
Jim Grosbach080a4992011-10-28 00:06:50 +00002989 // vector register lists must be contiguous.
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002990 // It's OK to use the enumeration values directly here rather, as the
2991 // VFP register classes have the enum sorted properly.
Jim Grosbach080a4992011-10-28 00:06:50 +00002992 //
2993 // The list is of D registers, but we also allow Q regs and just interpret
2994 // them as the two D sub-registers.
2995 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
Jim Grosbach2f50e922011-12-15 21:44:33 +00002996 if (!Spacing)
2997 Spacing = 1; // Register range implies a single spaced list.
2998 else if (Spacing == 2) {
2999 Error(RegLoc,
3000 "invalid register in double-spaced list (must be 'D' register')");
3001 return MatchOperand_ParseFail;
3002 }
Jim Grosbach080a4992011-10-28 00:06:50 +00003003 Reg = getDRegFromQReg(Reg);
3004 if (Reg != OldReg + 1) {
3005 Error(RegLoc, "non-contiguous register range");
3006 return MatchOperand_ParseFail;
3007 }
3008 ++Reg;
3009 Count += 2;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003010 // Parse the lane specifier if present.
3011 VectorLaneTy NextLaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00003012 unsigned NextLaneIndex;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003013 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach04945c42011-12-02 00:35:16 +00003014 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003015 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00003016 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003017 Error(EndLoc, "mismatched lane index in register list");
3018 return MatchOperand_ParseFail;
3019 }
Jim Grosbach080a4992011-10-28 00:06:50 +00003020 continue;
3021 }
Jim Grosbach2f50e922011-12-15 21:44:33 +00003022 // Normal D register.
3023 // Figure out the register spacing (single or double) of the list if
3024 // we don't know it already.
3025 if (!Spacing)
3026 Spacing = 1 + (Reg == OldReg + 2);
3027
3028 // Just check that it's contiguous and keep going.
3029 if (Reg != OldReg + Spacing) {
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003030 Error(RegLoc, "non-contiguous register range");
3031 return MatchOperand_ParseFail;
3032 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003033 ++Count;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003034 // Parse the lane specifier if present.
3035 VectorLaneTy NextLaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00003036 unsigned NextLaneIndex;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003037 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach04945c42011-12-02 00:35:16 +00003038 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003039 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00003040 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003041 Error(EndLoc, "mismatched lane index in register list");
3042 return MatchOperand_ParseFail;
3043 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003044 }
3045
3046 SMLoc E = Parser.getTok().getLoc();
3047 if (Parser.getTok().isNot(AsmToken::RCurly)) {
3048 Error(E, "'}' expected");
3049 return MatchOperand_ParseFail;
3050 }
3051 Parser.Lex(); // Eat '}' token.
3052
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003053 switch (LaneKind) {
3054 default:
3055 assert(0 && "unexpected lane kind in register list.");
3056 case NoLanes:
Jim Grosbach2f50e922011-12-15 21:44:33 +00003057 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count,
3058 (Spacing == 2), S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003059 break;
3060 case AllLanes:
3061 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
3062 S, E));
3063 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00003064 case IndexedLane:
3065 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
Jim Grosbach75e2ab52011-12-20 19:21:26 +00003066 LaneIndex,
3067 (Spacing == 2),
3068 S, E));
Jim Grosbach04945c42011-12-02 00:35:16 +00003069 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003070 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003071 return MatchOperand_Success;
3072}
3073
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003074/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbach861e49c2011-02-12 01:34:40 +00003075ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003076parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003077 SMLoc S = Parser.getTok().getLoc();
3078 const AsmToken &Tok = Parser.getTok();
3079 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3080 StringRef OptStr = Tok.getString();
3081
3082 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
3083 .Case("sy", ARM_MB::SY)
3084 .Case("st", ARM_MB::ST)
Jim Grosbach44c3f082011-07-13 23:40:38 +00003085 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003086 .Case("ish", ARM_MB::ISH)
Jim Grosbach44c3f082011-07-13 23:40:38 +00003087 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003088 .Case("ishst", ARM_MB::ISHST)
3089 .Case("nsh", ARM_MB::NSH)
Jim Grosbach44c3f082011-07-13 23:40:38 +00003090 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003091 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach44c3f082011-07-13 23:40:38 +00003092 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003093 .Case("osh", ARM_MB::OSH)
3094 .Case("oshst", ARM_MB::OSHST)
3095 .Default(~0U);
3096
3097 if (Opt == ~0U)
Jim Grosbach861e49c2011-02-12 01:34:40 +00003098 return MatchOperand_NoMatch;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003099
3100 Parser.Lex(); // Eat identifier token.
3101 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00003102 return MatchOperand_Success;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003103}
3104
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003105/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003106ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003107parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003108 SMLoc S = Parser.getTok().getLoc();
3109 const AsmToken &Tok = Parser.getTok();
3110 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3111 StringRef IFlagsStr = Tok.getString();
3112
Owen Anderson10c5b122011-10-05 17:16:40 +00003113 // An iflags string of "none" is interpreted to mean that none of the AIF
3114 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003115 unsigned IFlags = 0;
Owen Anderson10c5b122011-10-05 17:16:40 +00003116 if (IFlagsStr != "none") {
3117 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
3118 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
3119 .Case("a", ARM_PROC::A)
3120 .Case("i", ARM_PROC::I)
3121 .Case("f", ARM_PROC::F)
3122 .Default(~0U);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003123
Owen Anderson10c5b122011-10-05 17:16:40 +00003124 // If some specific iflag is already set, it means that some letter is
3125 // present more than once, this is not acceptable.
3126 if (Flag == ~0U || (IFlags & Flag))
3127 return MatchOperand_NoMatch;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003128
Owen Anderson10c5b122011-10-05 17:16:40 +00003129 IFlags |= Flag;
3130 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003131 }
3132
3133 Parser.Lex(); // Eat identifier token.
3134 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
3135 return MatchOperand_Success;
3136}
3137
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003138/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003139ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003140parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003141 SMLoc S = Parser.getTok().getLoc();
3142 const AsmToken &Tok = Parser.getTok();
3143 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3144 StringRef Mask = Tok.getString();
3145
James Molloy21efa7d2011-09-28 14:21:38 +00003146 if (isMClass()) {
3147 // See ARMv6-M 10.1.1
3148 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
3149 .Case("apsr", 0)
3150 .Case("iapsr", 1)
3151 .Case("eapsr", 2)
3152 .Case("xpsr", 3)
3153 .Case("ipsr", 5)
3154 .Case("epsr", 6)
3155 .Case("iepsr", 7)
3156 .Case("msp", 8)
3157 .Case("psp", 9)
3158 .Case("primask", 16)
3159 .Case("basepri", 17)
3160 .Case("basepri_max", 18)
3161 .Case("faultmask", 19)
3162 .Case("control", 20)
3163 .Default(~0U);
3164
3165 if (FlagsVal == ~0U)
3166 return MatchOperand_NoMatch;
3167
3168 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
3169 // basepri, basepri_max and faultmask only valid for V7m.
3170 return MatchOperand_NoMatch;
3171
3172 Parser.Lex(); // Eat identifier token.
3173 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3174 return MatchOperand_Success;
3175 }
3176
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003177 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
3178 size_t Start = 0, Next = Mask.find('_');
3179 StringRef Flags = "";
Benjamin Kramer20baffb2011-11-06 20:37:06 +00003180 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003181 if (Next != StringRef::npos)
3182 Flags = Mask.slice(Next+1, Mask.size());
3183
3184 // FlagsVal contains the complete mask:
3185 // 3-0: Mask
3186 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3187 unsigned FlagsVal = 0;
3188
3189 if (SpecReg == "apsr") {
3190 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachd25c2cd2011-07-19 22:45:10 +00003191 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003192 .Case("g", 0x4) // same as CPSR_s
3193 .Case("nzcvqg", 0xc) // same as CPSR_fs
3194 .Default(~0U);
3195
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00003196 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003197 if (!Flags.empty())
3198 return MatchOperand_NoMatch;
3199 else
Jim Grosbach0ecd3952011-09-14 20:03:46 +00003200 FlagsVal = 8; // No flag
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00003201 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003202 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes54452132011-05-25 00:35:03 +00003203 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
3204 Flags = "fc";
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003205 for (int i = 0, e = Flags.size(); i != e; ++i) {
3206 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
3207 .Case("c", 1)
3208 .Case("x", 2)
3209 .Case("s", 4)
3210 .Case("f", 8)
3211 .Default(~0U);
3212
3213 // If some specific flag is already set, it means that some letter is
3214 // present more than once, this is not acceptable.
3215 if (FlagsVal == ~0U || (FlagsVal & Flag))
3216 return MatchOperand_NoMatch;
3217 FlagsVal |= Flag;
3218 }
3219 } else // No match for special register.
3220 return MatchOperand_NoMatch;
3221
Owen Anderson03a173e2011-10-21 18:43:28 +00003222 // Special register without flags is NOT equivalent to "fc" flags.
3223 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3224 // two lines would enable gas compatibility at the expense of breaking
3225 // round-tripping.
3226 //
3227 // if (!FlagsVal)
3228 // FlagsVal = 0x9;
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003229
3230 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3231 if (SpecReg == "spsr")
3232 FlagsVal |= 16;
3233
3234 Parser.Lex(); // Eat identifier token.
3235 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3236 return MatchOperand_Success;
3237}
3238
Jim Grosbach27c1e252011-07-21 17:23:04 +00003239ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3240parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3241 int Low, int High) {
3242 const AsmToken &Tok = Parser.getTok();
3243 if (Tok.isNot(AsmToken::Identifier)) {
3244 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3245 return MatchOperand_ParseFail;
3246 }
3247 StringRef ShiftName = Tok.getString();
Benjamin Kramer20baffb2011-11-06 20:37:06 +00003248 std::string LowerOp = Op.lower();
3249 std::string UpperOp = Op.upper();
Jim Grosbach27c1e252011-07-21 17:23:04 +00003250 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3251 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3252 return MatchOperand_ParseFail;
3253 }
3254 Parser.Lex(); // Eat shift type token.
3255
3256 // There must be a '#' and a shift amount.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003257 if (Parser.getTok().isNot(AsmToken::Hash) &&
3258 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach27c1e252011-07-21 17:23:04 +00003259 Error(Parser.getTok().getLoc(), "'#' expected");
3260 return MatchOperand_ParseFail;
3261 }
3262 Parser.Lex(); // Eat hash token.
3263
3264 const MCExpr *ShiftAmount;
3265 SMLoc Loc = Parser.getTok().getLoc();
3266 if (getParser().ParseExpression(ShiftAmount)) {
3267 Error(Loc, "illegal expression");
3268 return MatchOperand_ParseFail;
3269 }
3270 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3271 if (!CE) {
3272 Error(Loc, "constant expression expected");
3273 return MatchOperand_ParseFail;
3274 }
3275 int Val = CE->getValue();
3276 if (Val < Low || Val > High) {
3277 Error(Loc, "immediate value out of range");
3278 return MatchOperand_ParseFail;
3279 }
3280
3281 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3282
3283 return MatchOperand_Success;
3284}
3285
Jim Grosbach0a547702011-07-22 17:44:50 +00003286ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3287parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3288 const AsmToken &Tok = Parser.getTok();
3289 SMLoc S = Tok.getLoc();
3290 if (Tok.isNot(AsmToken::Identifier)) {
3291 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3292 return MatchOperand_ParseFail;
3293 }
3294 int Val = StringSwitch<int>(Tok.getString())
3295 .Case("be", 1)
3296 .Case("le", 0)
3297 .Default(-1);
3298 Parser.Lex(); // Eat the token.
3299
3300 if (Val == -1) {
3301 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3302 return MatchOperand_ParseFail;
3303 }
3304 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3305 getContext()),
3306 S, Parser.getTok().getLoc()));
3307 return MatchOperand_Success;
3308}
3309
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00003310/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3311/// instructions. Legal values are:
3312/// lsl #n 'n' in [0,31]
3313/// asr #n 'n' in [1,32]
3314/// n == 32 encoded as n == 0.
3315ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3316parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3317 const AsmToken &Tok = Parser.getTok();
3318 SMLoc S = Tok.getLoc();
3319 if (Tok.isNot(AsmToken::Identifier)) {
3320 Error(S, "shift operator 'asr' or 'lsl' expected");
3321 return MatchOperand_ParseFail;
3322 }
3323 StringRef ShiftName = Tok.getString();
3324 bool isASR;
3325 if (ShiftName == "lsl" || ShiftName == "LSL")
3326 isASR = false;
3327 else if (ShiftName == "asr" || ShiftName == "ASR")
3328 isASR = true;
3329 else {
3330 Error(S, "shift operator 'asr' or 'lsl' expected");
3331 return MatchOperand_ParseFail;
3332 }
3333 Parser.Lex(); // Eat the operator.
3334
3335 // A '#' and a shift amount.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003336 if (Parser.getTok().isNot(AsmToken::Hash) &&
3337 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00003338 Error(Parser.getTok().getLoc(), "'#' expected");
3339 return MatchOperand_ParseFail;
3340 }
3341 Parser.Lex(); // Eat hash token.
3342
3343 const MCExpr *ShiftAmount;
3344 SMLoc E = Parser.getTok().getLoc();
3345 if (getParser().ParseExpression(ShiftAmount)) {
3346 Error(E, "malformed shift expression");
3347 return MatchOperand_ParseFail;
3348 }
3349 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3350 if (!CE) {
3351 Error(E, "shift amount must be an immediate");
3352 return MatchOperand_ParseFail;
3353 }
3354
3355 int64_t Val = CE->getValue();
3356 if (isASR) {
3357 // Shift amount must be in [1,32]
3358 if (Val < 1 || Val > 32) {
3359 Error(E, "'asr' shift amount must be in range [1,32]");
3360 return MatchOperand_ParseFail;
3361 }
Owen Andersonf01e2de2011-09-26 21:06:22 +00003362 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3363 if (isThumb() && Val == 32) {
3364 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3365 return MatchOperand_ParseFail;
3366 }
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00003367 if (Val == 32) Val = 0;
3368 } else {
3369 // Shift amount must be in [1,32]
3370 if (Val < 0 || Val > 31) {
3371 Error(E, "'lsr' shift amount must be in range [0,31]");
3372 return MatchOperand_ParseFail;
3373 }
3374 }
3375
3376 E = Parser.getTok().getLoc();
3377 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3378
3379 return MatchOperand_Success;
3380}
3381
Jim Grosbach833b9d32011-07-27 20:15:40 +00003382/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3383/// of instructions. Legal values are:
3384/// ror #n 'n' in {0, 8, 16, 24}
3385ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3386parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3387 const AsmToken &Tok = Parser.getTok();
3388 SMLoc S = Tok.getLoc();
Jim Grosbach82213192011-09-19 20:29:33 +00003389 if (Tok.isNot(AsmToken::Identifier))
3390 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00003391 StringRef ShiftName = Tok.getString();
Jim Grosbach82213192011-09-19 20:29:33 +00003392 if (ShiftName != "ror" && ShiftName != "ROR")
3393 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00003394 Parser.Lex(); // Eat the operator.
3395
3396 // A '#' and a rotate amount.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003397 if (Parser.getTok().isNot(AsmToken::Hash) &&
3398 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach833b9d32011-07-27 20:15:40 +00003399 Error(Parser.getTok().getLoc(), "'#' expected");
3400 return MatchOperand_ParseFail;
3401 }
3402 Parser.Lex(); // Eat hash token.
3403
3404 const MCExpr *ShiftAmount;
3405 SMLoc E = Parser.getTok().getLoc();
3406 if (getParser().ParseExpression(ShiftAmount)) {
3407 Error(E, "malformed rotate expression");
3408 return MatchOperand_ParseFail;
3409 }
3410 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3411 if (!CE) {
3412 Error(E, "rotate amount must be an immediate");
3413 return MatchOperand_ParseFail;
3414 }
3415
3416 int64_t Val = CE->getValue();
3417 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3418 // normally, zero is represented in asm by omitting the rotate operand
3419 // entirely.
3420 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3421 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3422 return MatchOperand_ParseFail;
3423 }
3424
3425 E = Parser.getTok().getLoc();
3426 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3427
3428 return MatchOperand_Success;
3429}
3430
Jim Grosbach864b6092011-07-28 21:34:26 +00003431ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3432parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3433 SMLoc S = Parser.getTok().getLoc();
3434 // The bitfield descriptor is really two operands, the LSB and the width.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003435 if (Parser.getTok().isNot(AsmToken::Hash) &&
3436 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach864b6092011-07-28 21:34:26 +00003437 Error(Parser.getTok().getLoc(), "'#' expected");
3438 return MatchOperand_ParseFail;
3439 }
3440 Parser.Lex(); // Eat hash token.
3441
3442 const MCExpr *LSBExpr;
3443 SMLoc E = Parser.getTok().getLoc();
3444 if (getParser().ParseExpression(LSBExpr)) {
3445 Error(E, "malformed immediate expression");
3446 return MatchOperand_ParseFail;
3447 }
3448 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3449 if (!CE) {
3450 Error(E, "'lsb' operand must be an immediate");
3451 return MatchOperand_ParseFail;
3452 }
3453
3454 int64_t LSB = CE->getValue();
3455 // The LSB must be in the range [0,31]
3456 if (LSB < 0 || LSB > 31) {
3457 Error(E, "'lsb' operand must be in the range [0,31]");
3458 return MatchOperand_ParseFail;
3459 }
3460 E = Parser.getTok().getLoc();
3461
3462 // Expect another immediate operand.
3463 if (Parser.getTok().isNot(AsmToken::Comma)) {
3464 Error(Parser.getTok().getLoc(), "too few operands");
3465 return MatchOperand_ParseFail;
3466 }
3467 Parser.Lex(); // Eat hash token.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003468 if (Parser.getTok().isNot(AsmToken::Hash) &&
3469 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach864b6092011-07-28 21:34:26 +00003470 Error(Parser.getTok().getLoc(), "'#' expected");
3471 return MatchOperand_ParseFail;
3472 }
3473 Parser.Lex(); // Eat hash token.
3474
3475 const MCExpr *WidthExpr;
3476 if (getParser().ParseExpression(WidthExpr)) {
3477 Error(E, "malformed immediate expression");
3478 return MatchOperand_ParseFail;
3479 }
3480 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3481 if (!CE) {
3482 Error(E, "'width' operand must be an immediate");
3483 return MatchOperand_ParseFail;
3484 }
3485
3486 int64_t Width = CE->getValue();
3487 // The LSB must be in the range [1,32-lsb]
3488 if (Width < 1 || Width > 32 - LSB) {
3489 Error(E, "'width' operand must be in the range [1,32-lsb]");
3490 return MatchOperand_ParseFail;
3491 }
3492 E = Parser.getTok().getLoc();
3493
3494 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3495
3496 return MatchOperand_Success;
3497}
3498
Jim Grosbachd3595712011-08-03 23:50:40 +00003499ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3500parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3501 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachc320c852011-08-05 21:28:30 +00003502 // postidx_reg := '+' register {, shift}
3503 // | '-' register {, shift}
3504 // | register {, shift}
Jim Grosbachd3595712011-08-03 23:50:40 +00003505
3506 // This method must return MatchOperand_NoMatch without consuming any tokens
3507 // in the case where there is no match, as other alternatives take other
3508 // parse methods.
3509 AsmToken Tok = Parser.getTok();
3510 SMLoc S = Tok.getLoc();
3511 bool haveEaten = false;
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00003512 bool isAdd = true;
Jim Grosbachd3595712011-08-03 23:50:40 +00003513 int Reg = -1;
3514 if (Tok.is(AsmToken::Plus)) {
3515 Parser.Lex(); // Eat the '+' token.
3516 haveEaten = true;
3517 } else if (Tok.is(AsmToken::Minus)) {
3518 Parser.Lex(); // Eat the '-' token.
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00003519 isAdd = false;
Jim Grosbachd3595712011-08-03 23:50:40 +00003520 haveEaten = true;
3521 }
3522 if (Parser.getTok().is(AsmToken::Identifier))
3523 Reg = tryParseRegister();
3524 if (Reg == -1) {
3525 if (!haveEaten)
3526 return MatchOperand_NoMatch;
3527 Error(Parser.getTok().getLoc(), "register expected");
3528 return MatchOperand_ParseFail;
3529 }
3530 SMLoc E = Parser.getTok().getLoc();
3531
Jim Grosbachc320c852011-08-05 21:28:30 +00003532 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3533 unsigned ShiftImm = 0;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00003534 if (Parser.getTok().is(AsmToken::Comma)) {
3535 Parser.Lex(); // Eat the ','.
3536 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3537 return MatchOperand_ParseFail;
3538 }
Jim Grosbachc320c852011-08-05 21:28:30 +00003539
3540 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3541 ShiftImm, S, E));
Jim Grosbachd3595712011-08-03 23:50:40 +00003542
3543 return MatchOperand_Success;
3544}
3545
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00003546ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3547parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3548 // Check for a post-index addressing register operand. Specifically:
3549 // am3offset := '+' register
3550 // | '-' register
3551 // | register
3552 // | # imm
3553 // | # + imm
3554 // | # - imm
3555
3556 // This method must return MatchOperand_NoMatch without consuming any tokens
3557 // in the case where there is no match, as other alternatives take other
3558 // parse methods.
3559 AsmToken Tok = Parser.getTok();
3560 SMLoc S = Tok.getLoc();
3561
3562 // Do immediates first, as we always parse those if we have a '#'.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003563 if (Parser.getTok().is(AsmToken::Hash) ||
3564 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00003565 Parser.Lex(); // Eat the '#'.
3566 // Explicitly look for a '-', as we need to encode negative zero
3567 // differently.
3568 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3569 const MCExpr *Offset;
3570 if (getParser().ParseExpression(Offset))
3571 return MatchOperand_ParseFail;
3572 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3573 if (!CE) {
3574 Error(S, "constant expression expected");
3575 return MatchOperand_ParseFail;
3576 }
3577 SMLoc E = Tok.getLoc();
3578 // Negative zero is encoded as the flag value INT32_MIN.
3579 int32_t Val = CE->getValue();
3580 if (isNegative && Val == 0)
3581 Val = INT32_MIN;
3582
3583 Operands.push_back(
3584 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3585
3586 return MatchOperand_Success;
3587 }
3588
3589
3590 bool haveEaten = false;
3591 bool isAdd = true;
3592 int Reg = -1;
3593 if (Tok.is(AsmToken::Plus)) {
3594 Parser.Lex(); // Eat the '+' token.
3595 haveEaten = true;
3596 } else if (Tok.is(AsmToken::Minus)) {
3597 Parser.Lex(); // Eat the '-' token.
3598 isAdd = false;
3599 haveEaten = true;
3600 }
3601 if (Parser.getTok().is(AsmToken::Identifier))
3602 Reg = tryParseRegister();
3603 if (Reg == -1) {
3604 if (!haveEaten)
3605 return MatchOperand_NoMatch;
3606 Error(Parser.getTok().getLoc(), "register expected");
3607 return MatchOperand_ParseFail;
3608 }
3609 SMLoc E = Parser.getTok().getLoc();
3610
3611 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3612 0, S, E));
3613
3614 return MatchOperand_Success;
3615}
3616
Jim Grosbach7db8d692011-09-08 22:07:06 +00003617/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3618/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3619/// when they refer multiple MIOperands inside a single one.
3620bool ARMAsmParser::
3621cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3622 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3623 // Rt, Rt2
3624 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3625 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3626 // Create a writeback register dummy placeholder.
3627 Inst.addOperand(MCOperand::CreateReg(0));
3628 // addr
3629 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3630 // pred
3631 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3632 return true;
3633}
3634
3635/// cvtT2StrdPre - Convert parsed operands to MCInst.
3636/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3637/// when they refer multiple MIOperands inside a single one.
3638bool ARMAsmParser::
3639cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3640 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3641 // Create a writeback register dummy placeholder.
3642 Inst.addOperand(MCOperand::CreateReg(0));
3643 // Rt, Rt2
3644 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3645 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3646 // addr
3647 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3648 // pred
3649 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3650 return true;
3651}
3652
Jim Grosbachc086f682011-09-08 00:39:19 +00003653/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3654/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3655/// when they refer multiple MIOperands inside a single one.
3656bool ARMAsmParser::
3657cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3658 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3659 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3660
3661 // Create a writeback register dummy placeholder.
3662 Inst.addOperand(MCOperand::CreateImm(0));
3663
3664 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3665 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3666 return true;
3667}
3668
Jim Grosbach9c0b86a2011-09-16 21:55:56 +00003669/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3670/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3671/// when they refer multiple MIOperands inside a single one.
3672bool ARMAsmParser::
3673cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3674 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3675 // Create a writeback register dummy placeholder.
3676 Inst.addOperand(MCOperand::CreateImm(0));
3677 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3678 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3679 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3680 return true;
3681}
3682
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003683/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003684/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3685/// when they refer multiple MIOperands inside a single one.
3686bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003687cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003688 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3689 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3690
3691 // Create a writeback register dummy placeholder.
3692 Inst.addOperand(MCOperand::CreateImm(0));
3693
Jim Grosbachd3595712011-08-03 23:50:40 +00003694 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003695 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3696 return true;
3697}
3698
Owen Anderson16d33f32011-08-26 20:43:14 +00003699/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3700/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3701/// when they refer multiple MIOperands inside a single one.
3702bool ARMAsmParser::
3703cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3704 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3705 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3706
3707 // Create a writeback register dummy placeholder.
3708 Inst.addOperand(MCOperand::CreateImm(0));
3709
3710 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3711 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3712 return true;
3713}
3714
3715
Jim Grosbachd564bf32011-08-11 19:22:40 +00003716/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3717/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3718/// when they refer multiple MIOperands inside a single one.
3719bool ARMAsmParser::
3720cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3721 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3722 // Create a writeback register dummy placeholder.
3723 Inst.addOperand(MCOperand::CreateImm(0));
3724 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3725 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3726 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3727 return true;
3728}
3729
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003730/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003731/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3732/// when they refer multiple MIOperands inside a single one.
3733bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003734cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003735 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3736 // Create a writeback register dummy placeholder.
3737 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd564bf32011-08-11 19:22:40 +00003738 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3739 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3740 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbachd3595712011-08-03 23:50:40 +00003741 return true;
3742}
3743
Jim Grosbachd886f8c2011-08-11 21:17:22 +00003744/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3745/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3746/// when they refer multiple MIOperands inside a single one.
3747bool ARMAsmParser::
3748cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3749 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3750 // Create a writeback register dummy placeholder.
3751 Inst.addOperand(MCOperand::CreateImm(0));
3752 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3753 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3754 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3755 return true;
3756}
3757
Jim Grosbachd3595712011-08-03 23:50:40 +00003758/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3759/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3760/// when they refer multiple MIOperands inside a single one.
3761bool ARMAsmParser::
3762cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3763 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3764 // Rt
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003765 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbachd3595712011-08-03 23:50:40 +00003766 // Create a writeback register dummy placeholder.
3767 Inst.addOperand(MCOperand::CreateImm(0));
3768 // addr
3769 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3770 // offset
3771 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3772 // pred
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003773 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3774 return true;
3775}
3776
Jim Grosbachd3595712011-08-03 23:50:40 +00003777/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003778/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3779/// when they refer multiple MIOperands inside a single one.
3780bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003781cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3782 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3783 // Rt
Owen Andersonb0e68992011-07-28 17:18:57 +00003784 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003785 // Create a writeback register dummy placeholder.
3786 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd3595712011-08-03 23:50:40 +00003787 // addr
3788 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3789 // offset
3790 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3791 // pred
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003792 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3793 return true;
3794}
3795
Jim Grosbachd3595712011-08-03 23:50:40 +00003796/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003797/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3798/// when they refer multiple MIOperands inside a single one.
3799bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003800cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3801 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003802 // Create a writeback register dummy placeholder.
3803 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd3595712011-08-03 23:50:40 +00003804 // Rt
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003805 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbachd3595712011-08-03 23:50:40 +00003806 // addr
3807 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3808 // offset
3809 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3810 // pred
3811 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3812 return true;
3813}
3814
3815/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3816/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3817/// when they refer multiple MIOperands inside a single one.
3818bool ARMAsmParser::
3819cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3820 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3821 // Create a writeback register dummy placeholder.
3822 Inst.addOperand(MCOperand::CreateImm(0));
3823 // Rt
3824 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3825 // addr
3826 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3827 // offset
3828 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3829 // pred
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003830 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3831 return true;
3832}
3833
Jim Grosbach5b96b802011-08-10 20:29:19 +00003834/// cvtLdrdPre - Convert parsed operands to MCInst.
3835/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3836/// when they refer multiple MIOperands inside a single one.
3837bool ARMAsmParser::
3838cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3839 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3840 // Rt, Rt2
3841 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3842 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3843 // Create a writeback register dummy placeholder.
3844 Inst.addOperand(MCOperand::CreateImm(0));
3845 // addr
3846 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3847 // pred
3848 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3849 return true;
3850}
3851
Jim Grosbacheb09f492011-08-11 20:28:23 +00003852/// cvtStrdPre - Convert parsed operands to MCInst.
3853/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3854/// when they refer multiple MIOperands inside a single one.
3855bool ARMAsmParser::
3856cvtStrdPre(MCInst &Inst, unsigned Opcode,
3857 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3858 // Create a writeback register dummy placeholder.
3859 Inst.addOperand(MCOperand::CreateImm(0));
3860 // Rt, Rt2
3861 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3862 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3863 // addr
3864 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3865 // pred
3866 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3867 return true;
3868}
3869
Jim Grosbachcd4dd252011-08-10 22:42:16 +00003870/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3871/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3872/// when they refer multiple MIOperands inside a single one.
3873bool ARMAsmParser::
3874cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3875 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3876 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3877 // Create a writeback register dummy placeholder.
3878 Inst.addOperand(MCOperand::CreateImm(0));
3879 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3880 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3881 return true;
3882}
3883
Jim Grosbach8e048492011-08-19 22:07:46 +00003884/// cvtThumbMultiple- Convert parsed operands to MCInst.
3885/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3886/// when they refer multiple MIOperands inside a single one.
3887bool ARMAsmParser::
3888cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3889 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3890 // The second source operand must be the same register as the destination
3891 // operand.
3892 if (Operands.size() == 6 &&
Jim Grosbach459422d2011-08-19 22:30:46 +00003893 (((ARMOperand*)Operands[3])->getReg() !=
3894 ((ARMOperand*)Operands[5])->getReg()) &&
3895 (((ARMOperand*)Operands[3])->getReg() !=
3896 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach8e048492011-08-19 22:07:46 +00003897 Error(Operands[3]->getStartLoc(),
Jim Grosbach459422d2011-08-19 22:30:46 +00003898 "destination register must match source register");
Jim Grosbach8e048492011-08-19 22:07:46 +00003899 return false;
3900 }
3901 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3902 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach5a5ce632011-11-10 22:10:12 +00003903 // If we have a three-operand form, make sure to set Rn to be the operand
3904 // that isn't the same as Rd.
3905 unsigned RegOp = 4;
3906 if (Operands.size() == 6 &&
3907 ((ARMOperand*)Operands[4])->getReg() ==
3908 ((ARMOperand*)Operands[3])->getReg())
3909 RegOp = 5;
3910 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
3911 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach8e048492011-08-19 22:07:46 +00003912 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3913
3914 return true;
3915}
Jim Grosbachcd4dd252011-08-10 22:42:16 +00003916
Jim Grosbach3ea06572011-10-24 22:16:58 +00003917bool ARMAsmParser::
3918cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3919 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3920 // Vd
Jim Grosbach182b6a02011-11-29 23:51:09 +00003921 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach3ea06572011-10-24 22:16:58 +00003922 // Create a writeback register dummy placeholder.
3923 Inst.addOperand(MCOperand::CreateImm(0));
3924 // Vn
3925 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3926 // pred
3927 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3928 return true;
3929}
3930
3931bool ARMAsmParser::
3932cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3933 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3934 // Vd
Jim Grosbach182b6a02011-11-29 23:51:09 +00003935 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach3ea06572011-10-24 22:16:58 +00003936 // Create a writeback register dummy placeholder.
3937 Inst.addOperand(MCOperand::CreateImm(0));
3938 // Vn
3939 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3940 // Vm
3941 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3942 // pred
3943 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3944 return true;
3945}
3946
Jim Grosbach05df4602011-10-31 21:50:31 +00003947bool ARMAsmParser::
3948cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
3949 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3950 // Create a writeback register dummy placeholder.
3951 Inst.addOperand(MCOperand::CreateImm(0));
3952 // Vn
3953 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3954 // Vt
Jim Grosbach182b6a02011-11-29 23:51:09 +00003955 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach05df4602011-10-31 21:50:31 +00003956 // pred
3957 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3958 return true;
3959}
3960
3961bool ARMAsmParser::
3962cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
3963 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3964 // Create a writeback register dummy placeholder.
3965 Inst.addOperand(MCOperand::CreateImm(0));
3966 // Vn
3967 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3968 // Vm
3969 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3970 // Vt
Jim Grosbach182b6a02011-11-29 23:51:09 +00003971 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach05df4602011-10-31 21:50:31 +00003972 // pred
3973 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3974 return true;
3975}
3976
Bill Wendlinge18980a2010-11-06 22:36:58 +00003977/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003978/// or an error. The first token must be a '[' when called.
Bill Wendling2063b842010-11-18 23:43:05 +00003979bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003980parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003981 SMLoc S, E;
Sean Callanan936b0d32010-01-19 21:44:56 +00003982 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00003983 "Token is not a Left Bracket");
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003984 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00003985 Parser.Lex(); // Eat left bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003986
Sean Callanan936b0d32010-01-19 21:44:56 +00003987 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003988 int BaseRegNum = tryParseRegister();
Jim Grosbachd3595712011-08-03 23:50:40 +00003989 if (BaseRegNum == -1)
3990 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003991
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00003992 // The next token must either be a comma or a closing bracket.
3993 const AsmToken &Tok = Parser.getTok();
3994 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbachd3595712011-08-03 23:50:40 +00003995 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00003996
Jim Grosbachd3595712011-08-03 23:50:40 +00003997 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003998 E = Tok.getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00003999 Parser.Lex(); // Eat right bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004000
Jim Grosbachd3595712011-08-03 23:50:40 +00004001 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbacha95ec992011-10-11 17:29:55 +00004002 0, 0, false, S, E));
Jim Grosbach32ff5582010-11-29 23:18:01 +00004003
Jim Grosbach40700e02011-09-19 18:42:21 +00004004 // If there's a pre-indexing writeback marker, '!', just add it as a token
4005 // operand. It's rather odd, but syntactically valid.
4006 if (Parser.getTok().is(AsmToken::Exclaim)) {
4007 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4008 Parser.Lex(); // Eat the '!'.
4009 }
4010
Jim Grosbachd3595712011-08-03 23:50:40 +00004011 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004012 }
Daniel Dunbarf5164f42011-01-18 05:34:24 +00004013
Jim Grosbachd3595712011-08-03 23:50:40 +00004014 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
4015 Parser.Lex(); // Eat the comma.
Daniel Dunbarf5164f42011-01-18 05:34:24 +00004016
Jim Grosbacha95ec992011-10-11 17:29:55 +00004017 // If we have a ':', it's an alignment specifier.
4018 if (Parser.getTok().is(AsmToken::Colon)) {
4019 Parser.Lex(); // Eat the ':'.
4020 E = Parser.getTok().getLoc();
4021
4022 const MCExpr *Expr;
4023 if (getParser().ParseExpression(Expr))
4024 return true;
4025
4026 // The expression has to be a constant. Memory references with relocations
4027 // don't come through here, as they use the <label> forms of the relevant
4028 // instructions.
4029 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4030 if (!CE)
4031 return Error (E, "constant expression expected");
4032
4033 unsigned Align = 0;
4034 switch (CE->getValue()) {
4035 default:
Jim Grosbachcef98cd2011-12-19 18:31:43 +00004036 return Error(E,
4037 "alignment specifier must be 16, 32, 64, 128, or 256 bits");
4038 case 16: Align = 2; break;
4039 case 32: Align = 4; break;
Jim Grosbacha95ec992011-10-11 17:29:55 +00004040 case 64: Align = 8; break;
4041 case 128: Align = 16; break;
4042 case 256: Align = 32; break;
4043 }
4044
4045 // Now we should have the closing ']'
4046 E = Parser.getTok().getLoc();
4047 if (Parser.getTok().isNot(AsmToken::RBrac))
4048 return Error(E, "']' expected");
4049 Parser.Lex(); // Eat right bracket token.
4050
4051 // Don't worry about range checking the value here. That's handled by
4052 // the is*() predicates.
4053 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
4054 ARM_AM::no_shift, 0, Align,
4055 false, S, E));
4056
4057 // If there's a pre-indexing writeback marker, '!', just add it as a token
4058 // operand.
4059 if (Parser.getTok().is(AsmToken::Exclaim)) {
4060 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4061 Parser.Lex(); // Eat the '!'.
4062 }
4063
4064 return false;
4065 }
4066
4067 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach8279c182011-11-15 22:14:41 +00004068 // offset. Be friendly and also accept a plain integer (without a leading
4069 // hash) for gas compatibility.
4070 if (Parser.getTok().is(AsmToken::Hash) ||
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004071 Parser.getTok().is(AsmToken::Dollar) ||
Jim Grosbach8279c182011-11-15 22:14:41 +00004072 Parser.getTok().is(AsmToken::Integer)) {
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004073 if (Parser.getTok().isNot(AsmToken::Integer))
Jim Grosbach8279c182011-11-15 22:14:41 +00004074 Parser.Lex(); // Eat the '#'.
Jim Grosbachd3595712011-08-03 23:50:40 +00004075 E = Parser.getTok().getLoc();
Daniel Dunbarf5164f42011-01-18 05:34:24 +00004076
Owen Anderson967674d2011-08-29 19:36:44 +00004077 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbachd3595712011-08-03 23:50:40 +00004078 const MCExpr *Offset;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004079 if (getParser().ParseExpression(Offset))
4080 return true;
Jim Grosbachd3595712011-08-03 23:50:40 +00004081
4082 // The expression has to be a constant. Memory references with relocations
4083 // don't come through here, as they use the <label> forms of the relevant
4084 // instructions.
4085 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
4086 if (!CE)
4087 return Error (E, "constant expression expected");
4088
Owen Anderson967674d2011-08-29 19:36:44 +00004089 // If the constant was #-0, represent it as INT32_MIN.
4090 int32_t Val = CE->getValue();
4091 if (isNegative && Val == 0)
4092 CE = MCConstantExpr::Create(INT32_MIN, getContext());
4093
Jim Grosbachd3595712011-08-03 23:50:40 +00004094 // Now we should have the closing ']'
4095 E = Parser.getTok().getLoc();
4096 if (Parser.getTok().isNot(AsmToken::RBrac))
4097 return Error(E, "']' expected");
4098 Parser.Lex(); // Eat right bracket token.
4099
4100 // Don't worry about range checking the value here. That's handled by
4101 // the is*() predicates.
4102 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbacha95ec992011-10-11 17:29:55 +00004103 ARM_AM::no_shift, 0, 0,
4104 false, S, E));
Jim Grosbachd3595712011-08-03 23:50:40 +00004105
4106 // If there's a pre-indexing writeback marker, '!', just add it as a token
4107 // operand.
4108 if (Parser.getTok().is(AsmToken::Exclaim)) {
4109 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4110 Parser.Lex(); // Eat the '!'.
4111 }
4112
4113 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004114 }
Jim Grosbachd3595712011-08-03 23:50:40 +00004115
4116 // The register offset is optionally preceded by a '+' or '-'
4117 bool isNegative = false;
4118 if (Parser.getTok().is(AsmToken::Minus)) {
4119 isNegative = true;
4120 Parser.Lex(); // Eat the '-'.
4121 } else if (Parser.getTok().is(AsmToken::Plus)) {
4122 // Nothing to do.
4123 Parser.Lex(); // Eat the '+'.
4124 }
4125
4126 E = Parser.getTok().getLoc();
4127 int OffsetRegNum = tryParseRegister();
4128 if (OffsetRegNum == -1)
4129 return Error(E, "register expected");
4130
4131 // If there's a shift operator, handle it.
4132 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00004133 unsigned ShiftImm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00004134 if (Parser.getTok().is(AsmToken::Comma)) {
4135 Parser.Lex(); // Eat the ','.
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00004136 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbachd3595712011-08-03 23:50:40 +00004137 return true;
4138 }
4139
4140 // Now we should have the closing ']'
4141 E = Parser.getTok().getLoc();
4142 if (Parser.getTok().isNot(AsmToken::RBrac))
4143 return Error(E, "']' expected");
4144 Parser.Lex(); // Eat right bracket token.
4145
4146 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbacha95ec992011-10-11 17:29:55 +00004147 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbachd3595712011-08-03 23:50:40 +00004148 S, E));
4149
Jim Grosbachc320c852011-08-05 21:28:30 +00004150 // If there's a pre-indexing writeback marker, '!', just add it as a token
4151 // operand.
4152 if (Parser.getTok().is(AsmToken::Exclaim)) {
4153 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4154 Parser.Lex(); // Eat the '!'.
4155 }
Jim Grosbachd3595712011-08-03 23:50:40 +00004156
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004157 return false;
4158}
4159
Jim Grosbachd3595712011-08-03 23:50:40 +00004160/// parseMemRegOffsetShift - one of these two:
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004161/// ( lsl | lsr | asr | ror ) , # shift_amount
4162/// rrx
Jim Grosbachd3595712011-08-03 23:50:40 +00004163/// return true if it parses a shift otherwise it returns false.
4164bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
4165 unsigned &Amount) {
4166 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan936b0d32010-01-19 21:44:56 +00004167 const AsmToken &Tok = Parser.getTok();
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004168 if (Tok.isNot(AsmToken::Identifier))
4169 return true;
Benjamin Kramer92d89982010-07-14 22:38:02 +00004170 StringRef ShiftName = Tok.getString();
Jim Grosbach3b559ff2011-12-07 23:40:58 +00004171 if (ShiftName == "lsl" || ShiftName == "LSL" ||
4172 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004173 St = ARM_AM::lsl;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004174 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004175 St = ARM_AM::lsr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004176 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004177 St = ARM_AM::asr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004178 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004179 St = ARM_AM::ror;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004180 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004181 St = ARM_AM::rrx;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004182 else
Jim Grosbachd3595712011-08-03 23:50:40 +00004183 return Error(Loc, "illegal shift operator");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004184 Parser.Lex(); // Eat shift type token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004185
Jim Grosbachd3595712011-08-03 23:50:40 +00004186 // rrx stands alone.
4187 Amount = 0;
4188 if (St != ARM_AM::rrx) {
4189 Loc = Parser.getTok().getLoc();
4190 // A '#' and a shift amount.
4191 const AsmToken &HashTok = Parser.getTok();
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004192 if (HashTok.isNot(AsmToken::Hash) &&
4193 HashTok.isNot(AsmToken::Dollar))
Jim Grosbachd3595712011-08-03 23:50:40 +00004194 return Error(HashTok.getLoc(), "'#' expected");
4195 Parser.Lex(); // Eat hash token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004196
Jim Grosbachd3595712011-08-03 23:50:40 +00004197 const MCExpr *Expr;
4198 if (getParser().ParseExpression(Expr))
4199 return true;
4200 // Range check the immediate.
4201 // lsl, ror: 0 <= imm <= 31
4202 // lsr, asr: 0 <= imm <= 32
4203 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4204 if (!CE)
4205 return Error(Loc, "shift amount must be an immediate");
4206 int64_t Imm = CE->getValue();
4207 if (Imm < 0 ||
4208 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4209 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4210 return Error(Loc, "immediate shift value out of range");
4211 Amount = Imm;
4212 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004213
4214 return false;
4215}
4216
Jim Grosbache7fbce72011-10-03 23:38:36 +00004217/// parseFPImm - A floating point immediate expression operand.
4218ARMAsmParser::OperandMatchResultTy ARMAsmParser::
4219parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4220 SMLoc S = Parser.getTok().getLoc();
4221
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004222 if (Parser.getTok().isNot(AsmToken::Hash) &&
4223 Parser.getTok().isNot(AsmToken::Dollar))
Jim Grosbache7fbce72011-10-03 23:38:36 +00004224 return MatchOperand_NoMatch;
Jim Grosbach741cd732011-10-17 22:26:03 +00004225
4226 // Disambiguate the VMOV forms that can accept an FP immediate.
4227 // vmov.f32 <sreg>, #imm
4228 // vmov.f64 <dreg>, #imm
4229 // vmov.f32 <dreg>, #imm @ vector f32x2
4230 // vmov.f32 <qreg>, #imm @ vector f32x4
4231 //
4232 // There are also the NEON VMOV instructions which expect an
4233 // integer constant. Make sure we don't try to parse an FPImm
4234 // for these:
4235 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4236 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4237 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4238 TyOp->getToken() != ".f64"))
4239 return MatchOperand_NoMatch;
4240
Jim Grosbache7fbce72011-10-03 23:38:36 +00004241 Parser.Lex(); // Eat the '#'.
4242
4243 // Handle negation, as that still comes through as a separate token.
4244 bool isNegative = false;
4245 if (Parser.getTok().is(AsmToken::Minus)) {
4246 isNegative = true;
4247 Parser.Lex();
4248 }
4249 const AsmToken &Tok = Parser.getTok();
4250 if (Tok.is(AsmToken::Real)) {
4251 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
4252 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4253 // If we had a '-' in front, toggle the sign bit.
4254 IntVal ^= (uint64_t)isNegative << 63;
4255 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
4256 Parser.Lex(); // Eat the token.
4257 if (Val == -1) {
4258 TokError("floating point value out of range");
4259 return MatchOperand_ParseFail;
4260 }
4261 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
4262 return MatchOperand_Success;
4263 }
4264 if (Tok.is(AsmToken::Integer)) {
4265 int64_t Val = Tok.getIntVal();
4266 Parser.Lex(); // Eat the token.
4267 if (Val > 255 || Val < 0) {
4268 TokError("encoded floating point value out of range");
4269 return MatchOperand_ParseFail;
4270 }
4271 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
4272 return MatchOperand_Success;
4273 }
4274
4275 TokError("invalid floating point immediate");
4276 return MatchOperand_ParseFail;
4277}
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004278/// Parse a arm instruction operand. For now this parses the operand regardless
4279/// of the mnemonic.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004280bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004281 StringRef Mnemonic) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004282 SMLoc S, E;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004283
4284 // Check if the current operand has a custom associated parser, if so, try to
4285 // custom parse the operand, or fallback to the general approach.
Jim Grosbach861e49c2011-02-12 01:34:40 +00004286 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4287 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004288 return false;
Jim Grosbach861e49c2011-02-12 01:34:40 +00004289 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4290 // there was a match, but an error occurred, in which case, just return that
4291 // the operand parsing failed.
4292 if (ResTy == MatchOperand_ParseFail)
4293 return true;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004294
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004295 switch (getLexer().getKind()) {
Bill Wendlingee7f1f92010-11-06 21:42:12 +00004296 default:
4297 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling2063b842010-11-18 23:43:05 +00004298 return true;
Jim Grosbachbb24c592011-07-13 18:49:30 +00004299 case AsmToken::Identifier: {
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004300 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling2063b842010-11-18 23:43:05 +00004301 return false;
Jim Grosbach0d6022d2011-07-26 20:41:24 +00004302 int Res = tryParseShiftRegister(Operands);
Jim Grosbachbb24c592011-07-13 18:49:30 +00004303 if (Res == 0) // success
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004304 return false;
Jim Grosbachbb24c592011-07-13 18:49:30 +00004305 else if (Res == -1) // irrecoverable error
4306 return true;
Jim Grosbach4eda1452011-12-20 22:26:38 +00004307 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach4ab23b52011-10-03 21:12:43 +00004308 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
4309 S = Parser.getTok().getLoc();
4310 Parser.Lex();
4311 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
4312 return false;
4313 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00004314
4315 // Fall though for the Identifier case that is not a register or a
4316 // special name.
Jim Grosbachbb24c592011-07-13 18:49:30 +00004317 }
Jim Grosbach4e380352011-10-26 21:14:08 +00004318 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderbyb084be92011-01-13 20:32:36 +00004319 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach5c6b6342011-11-01 22:38:31 +00004320 case AsmToken::String: // quoted label names.
Kevin Enderbyb084be92011-01-13 20:32:36 +00004321 case AsmToken::Dot: { // . as a branch target
Kevin Enderby146dcf22009-10-15 20:48:48 +00004322 // This was not a register so parse other operands that start with an
4323 // identifier (like labels) as expressions and create them as immediates.
4324 const MCExpr *IdVal;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004325 S = Parser.getTok().getLoc();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004326 if (getParser().ParseExpression(IdVal))
Bill Wendling2063b842010-11-18 23:43:05 +00004327 return true;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004328 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling2063b842010-11-18 23:43:05 +00004329 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4330 return false;
4331 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004332 case AsmToken::LBrac:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004333 return parseMemory(Operands);
Kevin Enderbya2b99102009-10-09 21:12:28 +00004334 case AsmToken::LCurly:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004335 return parseRegisterList(Operands);
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004336 case AsmToken::Dollar:
Owen Andersonf02d98d2011-08-29 17:17:09 +00004337 case AsmToken::Hash: {
Kevin Enderby3a80dac2009-10-13 23:33:38 +00004338 // #42 -> immediate.
4339 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004340 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00004341 Parser.Lex();
Owen Andersonf02d98d2011-08-29 17:17:09 +00004342 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby146dcf22009-10-15 20:48:48 +00004343 const MCExpr *ImmVal;
4344 if (getParser().ParseExpression(ImmVal))
Bill Wendling2063b842010-11-18 23:43:05 +00004345 return true;
Owen Andersonf02d98d2011-08-29 17:17:09 +00004346 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbach7f1f3bd2011-11-01 22:37:37 +00004347 if (CE) {
4348 int32_t Val = CE->getValue();
4349 if (isNegative && Val == 0)
4350 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Andersonf02d98d2011-08-29 17:17:09 +00004351 }
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004352 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling2063b842010-11-18 23:43:05 +00004353 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4354 return false;
Owen Andersonf02d98d2011-08-29 17:17:09 +00004355 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00004356 case AsmToken::Colon: {
4357 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng965b3c72011-01-13 07:58:56 +00004358 // FIXME: Check it's an expression prefix,
4359 // e.g. (FOO - :lower16:BAR) isn't legal.
4360 ARMMCExpr::VariantKind RefKind;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004361 if (parsePrefix(RefKind))
Jason W Kim1f7bc072011-01-11 23:53:41 +00004362 return true;
4363
Evan Cheng965b3c72011-01-13 07:58:56 +00004364 const MCExpr *SubExprVal;
4365 if (getParser().ParseExpression(SubExprVal))
Jason W Kim1f7bc072011-01-11 23:53:41 +00004366 return true;
4367
Evan Cheng965b3c72011-01-13 07:58:56 +00004368 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4369 getContext());
Jason W Kim1f7bc072011-01-11 23:53:41 +00004370 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng965b3c72011-01-13 07:58:56 +00004371 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim1f7bc072011-01-11 23:53:41 +00004372 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004373 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00004374 }
4375}
4376
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004377// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng965b3c72011-01-13 07:58:56 +00004378// :lower16: and :upper16:.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004379bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng965b3c72011-01-13 07:58:56 +00004380 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim1f7bc072011-01-11 23:53:41 +00004381
4382 // :lower16: and :upper16: modifiers
Jason W Kim93229972011-01-13 00:27:00 +00004383 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim1f7bc072011-01-11 23:53:41 +00004384 Parser.Lex(); // Eat ':'
4385
4386 if (getLexer().isNot(AsmToken::Identifier)) {
4387 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4388 return true;
4389 }
4390
4391 StringRef IDVal = Parser.getTok().getIdentifier();
4392 if (IDVal == "lower16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00004393 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00004394 } else if (IDVal == "upper16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00004395 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00004396 } else {
4397 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4398 return true;
4399 }
4400 Parser.Lex();
4401
4402 if (getLexer().isNot(AsmToken::Colon)) {
4403 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4404 return true;
4405 }
4406 Parser.Lex(); // Eat the last ':'
4407 return false;
4408}
4409
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004410/// \brief Given a mnemonic, split out possible predication code and carry
4411/// setting letters to form a canonical mnemonic and flags.
4412//
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004413// FIXME: Would be nice to autogen this.
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004414// FIXME: This is a bit of a maze of special cases.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004415StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00004416 unsigned &PredicationCode,
4417 bool &CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004418 unsigned &ProcessorIMod,
4419 StringRef &ITMask) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004420 PredicationCode = ARMCC::AL;
4421 CarrySetting = false;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004422 ProcessorIMod = 0;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004423
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004424 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004425 //
4426 // FIXME: Would be nice to autogen this.
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00004427 if ((Mnemonic == "movs" && isThumb()) ||
4428 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4429 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4430 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4431 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4432 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4433 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
Jim Grosbache16acac2011-12-19 19:43:50 +00004434 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" ||
4435 Mnemonic == "fmuls")
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004436 return Mnemonic;
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004437
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00004438 // First, split out any predication code. Ignore mnemonics we know aren't
4439 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbach8d114902011-07-20 18:20:31 +00004440 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach0c398b92011-07-27 21:58:11 +00004441 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach3636be32011-08-22 23:55:58 +00004442 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbachf6d5d602011-09-01 18:22:13 +00004443 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00004444 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4445 .Case("eq", ARMCC::EQ)
4446 .Case("ne", ARMCC::NE)
4447 .Case("hs", ARMCC::HS)
4448 .Case("cs", ARMCC::HS)
4449 .Case("lo", ARMCC::LO)
4450 .Case("cc", ARMCC::LO)
4451 .Case("mi", ARMCC::MI)
4452 .Case("pl", ARMCC::PL)
4453 .Case("vs", ARMCC::VS)
4454 .Case("vc", ARMCC::VC)
4455 .Case("hi", ARMCC::HI)
4456 .Case("ls", ARMCC::LS)
4457 .Case("ge", ARMCC::GE)
4458 .Case("lt", ARMCC::LT)
4459 .Case("gt", ARMCC::GT)
4460 .Case("le", ARMCC::LE)
4461 .Case("al", ARMCC::AL)
4462 .Default(~0U);
4463 if (CC != ~0U) {
4464 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4465 PredicationCode = CC;
4466 }
Bill Wendling193961b2010-10-29 23:50:21 +00004467 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004468
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004469 // Next, determine if we have a carry setting bit. We explicitly ignore all
4470 // the instructions we know end in 's'.
4471 if (Mnemonic.endswith("s") &&
Jim Grosbachd3e8e292011-08-17 22:49:09 +00004472 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00004473 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4474 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4475 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach086d0132011-12-08 00:49:29 +00004476 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach54337b82011-12-10 00:01:02 +00004477 Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
Jim Grosbach92a939a2011-12-19 19:02:41 +00004478 Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" ||
Jim Grosbache16acac2011-12-19 19:43:50 +00004479 Mnemonic == "fmuls" ||
Jim Grosbach51726e22011-07-29 20:26:09 +00004480 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004481 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4482 CarrySetting = true;
4483 }
4484
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004485 // The "cps" instruction can have a interrupt mode operand which is glued into
4486 // the mnemonic. Check if this is the case, split it and parse the imod op
4487 if (Mnemonic.startswith("cps")) {
4488 // Split out any imod code.
4489 unsigned IMod =
4490 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4491 .Case("ie", ARM_PROC::IE)
4492 .Case("id", ARM_PROC::ID)
4493 .Default(~0U);
4494 if (IMod != ~0U) {
4495 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4496 ProcessorIMod = IMod;
4497 }
4498 }
4499
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004500 // The "it" instruction has the condition mask on the end of the mnemonic.
4501 if (Mnemonic.startswith("it")) {
4502 ITMask = Mnemonic.slice(2, Mnemonic.size());
4503 Mnemonic = Mnemonic.slice(0, 2);
4504 }
4505
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004506 return Mnemonic;
4507}
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004508
4509/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4510/// inclusion of carry set or predication code operands.
4511//
4512// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00004513void ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004514getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00004515 bool &CanAcceptPredicationCode) {
Daniel Dunbar09264122011-01-11 19:06:29 +00004516 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4517 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00004518 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00004519 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004520 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00004521 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004522 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00004523 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004524 Mnemonic == "mla" || Mnemonic == "smlal" ||
4525 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbar09264122011-01-11 19:06:29 +00004526 CanAcceptCarrySet = true;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004527 } else
Daniel Dunbar09264122011-01-11 19:06:29 +00004528 CanAcceptCarrySet = false;
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004529
Daniel Dunbar09264122011-01-11 19:06:29 +00004530 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4531 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4532 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4533 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbach803898f2011-09-06 20:27:04 +00004534 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4535 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach25977222011-08-19 23:24:36 +00004536 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach93981412011-10-11 21:55:36 +00004537 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4538 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4539 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbachb9d4e372011-08-26 22:21:51 +00004540 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4541 !isThumb()) ||
Jim Grosbachb908b7a2011-09-10 00:15:36 +00004542 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004543 CanAcceptPredicationCode = false;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004544 } else
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004545 CanAcceptPredicationCode = true;
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004546
Jim Grosbach6c45b752011-09-16 16:39:25 +00004547 if (isThumb()) {
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004548 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbachb98ab912011-06-30 22:10:46 +00004549 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004550 CanAcceptPredicationCode = false;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004551 }
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004552}
4553
Jim Grosbach7283da92011-08-16 21:12:37 +00004554bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4555 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004556 // FIXME: This is all horribly hacky. We really need a better way to deal
4557 // with optional operands like this in the matcher table.
Jim Grosbach7283da92011-08-16 21:12:37 +00004558
4559 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4560 // another does not. Specifically, the MOVW instruction does not. So we
4561 // special case it here and remove the defaulted (non-setting) cc_out
4562 // operand if that's the instruction we're trying to match.
4563 //
4564 // We do this as post-processing of the explicit operands rather than just
4565 // conditionally adding the cc_out in the first place because we need
4566 // to check the type of the parsed immediate operand.
Owen Andersond7791b92011-09-14 22:46:14 +00004567 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbach7283da92011-08-16 21:12:37 +00004568 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4569 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4570 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4571 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00004572
4573 // Register-register 'add' for thumb does not have a cc_out operand
4574 // when there are only two register operands.
4575 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4576 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4577 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4578 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4579 return true;
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004580 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004581 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4582 // have to check the immediate range here since Thumb2 has a variant
4583 // that can handle a different range and has a cc_out operand.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004584 if (((isThumb() && Mnemonic == "add") ||
4585 (isThumbTwo() && Mnemonic == "sub")) &&
4586 Operands.size() == 6 &&
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004587 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4588 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4589 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004590 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4591 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4592 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004593 return true;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004594 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4595 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004596 // selecting via the generic "add" mnemonic, so to know that we
4597 // should remove the cc_out operand, we have to explicitly check that
4598 // it's not one of the other variants. Ugh.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004599 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4600 Operands.size() == 6 &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004601 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4602 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4603 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4604 // Nest conditions rather than one big 'if' statement for readability.
4605 //
4606 // If either register is a high reg, it's either one of the SP
4607 // variants (handled above) or a 32-bit encoding, so we just
4608 // check against T3.
4609 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4610 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4611 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4612 return false;
4613 // If both registers are low, we're in an IT block, and the immediate is
4614 // in range, we should use encoding T1 instead, which has a cc_out.
4615 if (inITBlock() &&
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004616 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004617 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4618 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4619 return false;
4620
4621 // Otherwise, we use encoding T4, which does not have a cc_out
4622 // operand.
4623 return true;
4624 }
4625
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004626 // The thumb2 multiply instruction doesn't have a CCOut register, so
4627 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4628 // use the 16-bit encoding or not.
4629 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4630 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4631 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4632 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4633 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4634 // If the registers aren't low regs, the destination reg isn't the
4635 // same as one of the source regs, or the cc_out operand is zero
4636 // outside of an IT block, we have to use the 32-bit encoding, so
4637 // remove the cc_out operand.
4638 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4639 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach6efa7b92011-11-15 19:29:45 +00004640 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004641 !inITBlock() ||
4642 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4643 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4644 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4645 static_cast<ARMOperand*>(Operands[4])->getReg())))
4646 return true;
4647
Jim Grosbachefa7e952011-11-15 19:55:16 +00004648 // Also check the 'mul' syntax variant that doesn't specify an explicit
4649 // destination register.
4650 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4651 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4652 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4653 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4654 // If the registers aren't low regs or the cc_out operand is zero
4655 // outside of an IT block, we have to use the 32-bit encoding, so
4656 // remove the cc_out operand.
4657 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4658 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4659 !inITBlock()))
4660 return true;
4661
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004662
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004663
Jim Grosbach4b701af2011-08-24 21:42:27 +00004664 // Register-register 'add/sub' for thumb does not have a cc_out operand
4665 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4666 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4667 // right, this will result in better diagnostics (which operand is off)
4668 // anyway.
4669 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4670 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004671 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4672 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4673 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4674 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00004675
Jim Grosbach7283da92011-08-16 21:12:37 +00004676 return false;
4677}
4678
Jim Grosbach12952fe2011-11-11 23:08:10 +00004679static bool isDataTypeToken(StringRef Tok) {
4680 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4681 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4682 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4683 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4684 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4685 Tok == ".f" || Tok == ".d";
4686}
4687
4688// FIXME: This bit should probably be handled via an explicit match class
4689// in the .td files that matches the suffix instead of having it be
4690// a literal string token the way it is now.
4691static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4692 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4693}
4694
Jim Grosbach8be2f652011-12-09 23:34:09 +00004695static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004696/// Parse an arm instruction mnemonic followed by its operands.
4697bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4698 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach8be2f652011-12-09 23:34:09 +00004699 // Apply mnemonic aliases before doing anything else, as the destination
4700 // mnemnonic may include suffices and we want to handle them normally.
4701 // The generic tblgen'erated code does this later, at the start of
4702 // MatchInstructionImpl(), but that's too late for aliases that include
4703 // any sort of suffix.
4704 unsigned AvailableFeatures = getAvailableFeatures();
4705 applyMnemonicAliases(Name, AvailableFeatures);
4706
Jim Grosbachab5830e2011-12-14 02:16:11 +00004707 // First check for the ARM-specific .req directive.
4708 if (Parser.getTok().is(AsmToken::Identifier) &&
4709 Parser.getTok().getIdentifier() == ".req") {
4710 parseDirectiveReq(Name, NameLoc);
4711 // We always return 'error' for this, as we're done with this
4712 // statement and don't need to match the 'instruction."
4713 return true;
4714 }
4715
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004716 // Create the leading tokens for the mnemonic, split by '.' characters.
4717 size_t Start = 0, Next = Name.find('.');
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004718 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004719
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004720 // Split out the predication code and carry setting flag from the mnemonic.
4721 unsigned PredicationCode;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004722 unsigned ProcessorIMod;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004723 bool CarrySetting;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004724 StringRef ITMask;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004725 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004726 ProcessorIMod, ITMask);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004727
Jim Grosbach1c171b12011-08-25 17:23:55 +00004728 // In Thumb1, only the branch (B) instruction can be predicated.
4729 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4730 Parser.EatToEndOfStatement();
4731 return Error(NameLoc, "conditional execution not supported in Thumb1");
4732 }
4733
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004734 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4735
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004736 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4737 // is the mask as it will be for the IT encoding if the conditional
4738 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4739 // where the conditional bit0 is zero, the instruction post-processing
4740 // will adjust the mask accordingly.
4741 if (Mnemonic == "it") {
Jim Grosbached16ec42011-08-29 22:24:09 +00004742 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4743 if (ITMask.size() > 3) {
4744 Parser.EatToEndOfStatement();
4745 return Error(Loc, "too many conditions on IT instruction");
4746 }
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004747 unsigned Mask = 8;
4748 for (unsigned i = ITMask.size(); i != 0; --i) {
4749 char pos = ITMask[i - 1];
4750 if (pos != 't' && pos != 'e') {
4751 Parser.EatToEndOfStatement();
Jim Grosbached16ec42011-08-29 22:24:09 +00004752 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004753 }
4754 Mask >>= 1;
4755 if (ITMask[i - 1] == 't')
4756 Mask |= 8;
4757 }
Jim Grosbached16ec42011-08-29 22:24:09 +00004758 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004759 }
4760
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004761 // FIXME: This is all a pretty gross hack. We should automatically handle
4762 // optional operands like this via tblgen.
Bill Wendling219dabd2010-11-21 10:56:05 +00004763
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004764 // Next, add the CCOut and ConditionCode operands, if needed.
4765 //
4766 // For mnemonics which can ever incorporate a carry setting bit or predication
4767 // code, our matching model involves us always generating CCOut and
4768 // ConditionCode operands to match the mnemonic "as written" and then we let
4769 // the matcher deal with finding the right instruction or generating an
4770 // appropriate error.
4771 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004772 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004773
Jim Grosbach03a8a162011-07-14 22:04:21 +00004774 // If we had a carry-set on an instruction that can't do that, issue an
4775 // error.
4776 if (!CanAcceptCarrySet && CarrySetting) {
4777 Parser.EatToEndOfStatement();
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004778 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach03a8a162011-07-14 22:04:21 +00004779 "' can not set flags, but 's' suffix specified");
4780 }
Jim Grosbach0a547702011-07-22 17:44:50 +00004781 // If we had a predication code on an instruction that can't do that, issue an
4782 // error.
4783 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4784 Parser.EatToEndOfStatement();
4785 return Error(NameLoc, "instruction '" + Mnemonic +
4786 "' is not predicable, but condition code specified");
4787 }
Jim Grosbach03a8a162011-07-14 22:04:21 +00004788
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004789 // Add the carry setting operand, if necessary.
Jim Grosbached16ec42011-08-29 22:24:09 +00004790 if (CanAcceptCarrySet) {
4791 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004792 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbached16ec42011-08-29 22:24:09 +00004793 Loc));
4794 }
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004795
4796 // Add the predication code operand, if necessary.
4797 if (CanAcceptPredicationCode) {
Jim Grosbached16ec42011-08-29 22:24:09 +00004798 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4799 CarrySetting);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004800 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbached16ec42011-08-29 22:24:09 +00004801 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004802 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004803
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004804 // Add the processor imod operand, if necessary.
4805 if (ProcessorIMod) {
4806 Operands.push_back(ARMOperand::CreateImm(
4807 MCConstantExpr::Create(ProcessorIMod, getContext()),
4808 NameLoc, NameLoc));
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004809 }
4810
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004811 // Add the remaining tokens in the mnemonic.
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004812 while (Next != StringRef::npos) {
4813 Start = Next;
4814 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004815 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004816
Jim Grosbach12952fe2011-11-11 23:08:10 +00004817 // Some NEON instructions have an optional datatype suffix that is
4818 // completely ignored. Check for that.
4819 if (isDataTypeToken(ExtraToken) &&
4820 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4821 continue;
4822
Jim Grosbach39c6e1d2011-09-07 16:06:04 +00004823 if (ExtraToken != ".n") {
4824 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4825 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4826 }
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004827 }
4828
4829 // Read the remaining operands.
4830 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004831 // Read the first operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004832 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnera2a9d162010-09-11 16:18:25 +00004833 Parser.EatToEndOfStatement();
4834 return true;
4835 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004836
4837 while (getLexer().is(AsmToken::Comma)) {
Sean Callanana83fd7d2010-01-19 20:27:46 +00004838 Parser.Lex(); // Eat the comma.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004839
4840 // Parse and remember the operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004841 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnera2a9d162010-09-11 16:18:25 +00004842 Parser.EatToEndOfStatement();
4843 return true;
4844 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004845 }
4846 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00004847
Chris Lattnera2a9d162010-09-11 16:18:25 +00004848 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbachb8d9f512011-10-07 18:27:04 +00004849 SMLoc Loc = getLexer().getLoc();
Chris Lattnera2a9d162010-09-11 16:18:25 +00004850 Parser.EatToEndOfStatement();
Jim Grosbachb8d9f512011-10-07 18:27:04 +00004851 return Error(Loc, "unexpected token in argument list");
Chris Lattnera2a9d162010-09-11 16:18:25 +00004852 }
Bill Wendlingee7f1f92010-11-06 21:42:12 +00004853
Chris Lattner91689c12010-09-08 05:10:46 +00004854 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004855
Jim Grosbach7283da92011-08-16 21:12:37 +00004856 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4857 // do and don't have a cc_out optional-def operand. With some spot-checks
4858 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004859 // parse and adjust accordingly before actually matching. We shouldn't ever
4860 // try to remove a cc_out operand that was explicitly set on the the
4861 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4862 // table driven matcher doesn't fit well with the ARM instruction set.
4863 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004864 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4865 Operands.erase(Operands.begin() + 1);
4866 delete Op;
4867 }
4868
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00004869 // ARM mode 'blx' need special handling, as the register operand version
4870 // is predicable, but the label operand version is not. So, we can't rely
4871 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach6e5778f2011-10-07 23:24:09 +00004872 // a k_CondCode operand in the list. If we're trying to match the label
4873 // version, remove the k_CondCode operand here.
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00004874 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4875 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4876 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4877 Operands.erase(Operands.begin() + 1);
4878 delete Op;
4879 }
Jim Grosbach8cffa282011-08-11 23:51:13 +00004880
4881 // The vector-compare-to-zero instructions have a literal token "#0" at
4882 // the end that comes to here as an immediate operand. Convert it to a
4883 // token to play nicely with the matcher.
4884 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4885 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4886 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4887 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4888 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4889 if (CE && CE->getValue() == 0) {
4890 Operands.erase(Operands.begin() + 5);
4891 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4892 delete Op;
4893 }
4894 }
Jim Grosbach46b66462011-10-03 22:30:24 +00004895 // VCMP{E} does the same thing, but with a different operand count.
4896 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4897 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4898 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4899 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4900 if (CE && CE->getValue() == 0) {
4901 Operands.erase(Operands.begin() + 4);
4902 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4903 delete Op;
4904 }
4905 }
Jim Grosbachc3c32d92011-08-22 23:47:13 +00004906 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
Jim Grosbach1f1a3592011-12-13 20:50:38 +00004907 // end. Convert it to a token here. Take care not to convert those
4908 // that should hit the Thumb2 encoding.
Jim Grosbachc3c32d92011-08-22 23:47:13 +00004909 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
Jim Grosbach1f1a3592011-12-13 20:50:38 +00004910 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4911 static_cast<ARMOperand*>(Operands[4])->isReg() &&
Jim Grosbachc3c32d92011-08-22 23:47:13 +00004912 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4913 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4914 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
Jim Grosbach1f1a3592011-12-13 20:50:38 +00004915 if (CE && CE->getValue() == 0 &&
4916 (isThumbOne() ||
Jim Grosbach5ac89672011-12-13 21:06:41 +00004917 // The cc_out operand matches the IT block.
4918 ((inITBlock() != CarrySetting) &&
4919 // Neither register operand is a high register.
Jim Grosbach1f1a3592011-12-13 20:50:38 +00004920 (isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach5ac89672011-12-13 21:06:41 +00004921 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()))))){
Jim Grosbachc3c32d92011-08-22 23:47:13 +00004922 Operands.erase(Operands.begin() + 5);
4923 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4924 delete Op;
4925 }
4926 }
4927
Chris Lattnerf29c0b62010-01-14 22:21:20 +00004928 return false;
Kevin Enderbyccab3172009-09-15 00:27:25 +00004929}
4930
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004931// Validate context-sensitive operand constraints.
Jim Grosbach169b2be2011-08-23 18:13:04 +00004932
4933// return 'true' if register list contains non-low GPR registers,
4934// 'false' otherwise. If Reg is in the register list or is HiReg, set
4935// 'containsReg' to true.
4936static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4937 unsigned HiReg, bool &containsReg) {
4938 containsReg = false;
4939 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4940 unsigned OpReg = Inst.getOperand(i).getReg();
4941 if (OpReg == Reg)
4942 containsReg = true;
4943 // Anything other than a low register isn't legal here.
4944 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4945 return true;
4946 }
4947 return false;
4948}
4949
Jim Grosbacha31f2232011-09-07 18:05:34 +00004950// Check if the specified regisgter is in the register list of the inst,
4951// starting at the indicated operand number.
4952static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4953 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4954 unsigned OpReg = Inst.getOperand(i).getReg();
4955 if (OpReg == Reg)
4956 return true;
4957 }
4958 return false;
4959}
4960
Jim Grosbached16ec42011-08-29 22:24:09 +00004961// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4962// the ARMInsts array) instead. Getting that here requires awkward
4963// API changes, though. Better way?
4964namespace llvm {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00004965extern const MCInstrDesc ARMInsts[];
Jim Grosbached16ec42011-08-29 22:24:09 +00004966}
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00004967static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbached16ec42011-08-29 22:24:09 +00004968 return ARMInsts[Opcode];
4969}
4970
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004971// FIXME: We would really like to be able to tablegen'erate this.
4972bool ARMAsmParser::
4973validateInstruction(MCInst &Inst,
4974 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00004975 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbached16ec42011-08-29 22:24:09 +00004976 SMLoc Loc = Operands[0]->getStartLoc();
4977 // Check the IT block state first.
Owen Anderson44ae2da2011-09-13 17:59:19 +00004978 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4979 // being allowed in IT blocks, but not being predicable. It just always
4980 // executes.
4981 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbached16ec42011-08-29 22:24:09 +00004982 unsigned bit = 1;
4983 if (ITState.FirstCond)
4984 ITState.FirstCond = false;
4985 else
Jim Grosbacha0d34d32011-09-02 23:22:08 +00004986 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbached16ec42011-08-29 22:24:09 +00004987 // The instruction must be predicable.
4988 if (!MCID.isPredicable())
4989 return Error(Loc, "instructions in IT block must be predicable");
4990 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4991 unsigned ITCond = bit ? ITState.Cond :
4992 ARMCC::getOppositeCondition(ITState.Cond);
4993 if (Cond != ITCond) {
4994 // Find the condition code Operand to get its SMLoc information.
4995 SMLoc CondLoc;
4996 for (unsigned i = 1; i < Operands.size(); ++i)
4997 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4998 CondLoc = Operands[i]->getStartLoc();
4999 return Error(CondLoc, "incorrect condition in IT block; got '" +
5000 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
5001 "', but expected '" +
5002 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
5003 }
Jim Grosbachc61fc8f2011-08-31 18:29:05 +00005004 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00005005 } else if (isThumbTwo() && MCID.isPredicable() &&
5006 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson29cfe6c2011-09-09 21:48:23 +00005007 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
5008 Inst.getOpcode() != ARM::t2B)
Jim Grosbached16ec42011-08-29 22:24:09 +00005009 return Error(Loc, "predicated instructions must be in IT block");
5010
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005011 switch (Inst.getOpcode()) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00005012 case ARM::LDRD:
5013 case ARM::LDRD_PRE:
5014 case ARM::LDRD_POST:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005015 case ARM::LDREXD: {
5016 // Rt2 must be Rt + 1.
5017 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5018 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5019 if (Rt2 != Rt + 1)
5020 return Error(Operands[3]->getStartLoc(),
5021 "destination operands must be sequential");
5022 return false;
5023 }
Jim Grosbacheb09f492011-08-11 20:28:23 +00005024 case ARM::STRD: {
5025 // Rt2 must be Rt + 1.
5026 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5027 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5028 if (Rt2 != Rt + 1)
5029 return Error(Operands[3]->getStartLoc(),
5030 "source operands must be sequential");
5031 return false;
5032 }
Jim Grosbachf7164b22011-08-10 20:49:18 +00005033 case ARM::STRD_PRE:
5034 case ARM::STRD_POST:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005035 case ARM::STREXD: {
5036 // Rt2 must be Rt + 1.
5037 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5038 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
5039 if (Rt2 != Rt + 1)
Jim Grosbacheb09f492011-08-11 20:28:23 +00005040 return Error(Operands[3]->getStartLoc(),
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005041 "source operands must be sequential");
5042 return false;
5043 }
Jim Grosbach03f56d92011-07-27 21:09:25 +00005044 case ARM::SBFX:
5045 case ARM::UBFX: {
5046 // width must be in range [1, 32-lsb]
5047 unsigned lsb = Inst.getOperand(2).getImm();
5048 unsigned widthm1 = Inst.getOperand(3).getImm();
5049 if (widthm1 >= 32 - lsb)
5050 return Error(Operands[5]->getStartLoc(),
5051 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach64610e52011-08-16 21:42:31 +00005052 return false;
Jim Grosbach03f56d92011-07-27 21:09:25 +00005053 }
Jim Grosbach90103cc2011-08-18 21:50:53 +00005054 case ARM::tLDMIA: {
Jim Grosbacha31f2232011-09-07 18:05:34 +00005055 // If we're parsing Thumb2, the .w variant is available and handles
5056 // most cases that are normally illegal for a Thumb1 LDM
5057 // instruction. We'll make the transformation in processInstruction()
5058 // if necessary.
5059 //
Jim Grosbach90103cc2011-08-18 21:50:53 +00005060 // Thumb LDM instructions are writeback iff the base register is not
5061 // in the register list.
5062 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach139acd22011-08-22 23:01:07 +00005063 bool hasWritebackToken =
5064 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5065 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbach169b2be2011-08-23 18:13:04 +00005066 bool listContainsBase;
Jim Grosbacha31f2232011-09-07 18:05:34 +00005067 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00005068 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
5069 "registers must be in range r0-r7");
Jim Grosbach90103cc2011-08-18 21:50:53 +00005070 // If we should have writeback, then there should be a '!' token.
Jim Grosbacha31f2232011-09-07 18:05:34 +00005071 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach90103cc2011-08-18 21:50:53 +00005072 return Error(Operands[2]->getStartLoc(),
5073 "writeback operator '!' expected");
Jim Grosbacha31f2232011-09-07 18:05:34 +00005074 // If we should not have writeback, there must not be a '!'. This is
5075 // true even for the 32-bit wide encodings.
Jim Grosbach169b2be2011-08-23 18:13:04 +00005076 if (listContainsBase && hasWritebackToken)
Jim Grosbach139acd22011-08-22 23:01:07 +00005077 return Error(Operands[3]->getStartLoc(),
5078 "writeback operator '!' not allowed when base register "
5079 "in register list");
Jim Grosbach90103cc2011-08-18 21:50:53 +00005080
5081 break;
5082 }
Jim Grosbacha31f2232011-09-07 18:05:34 +00005083 case ARM::t2LDMIA_UPD: {
5084 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
5085 return Error(Operands[4]->getStartLoc(),
5086 "writeback operator '!' not allowed when base register "
5087 "in register list");
5088 break;
5089 }
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005090 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
5091 // so only issue a diagnostic for thumb1. The instructions will be
5092 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach38c59fc2011-08-22 23:17:34 +00005093 case ARM::tPOP: {
Jim Grosbach169b2be2011-08-23 18:13:04 +00005094 bool listContainsBase;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005095 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
5096 !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00005097 return Error(Operands[2]->getStartLoc(),
5098 "registers must be in range r0-r7 or pc");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00005099 break;
5100 }
5101 case ARM::tPUSH: {
Jim Grosbach169b2be2011-08-23 18:13:04 +00005102 bool listContainsBase;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005103 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
5104 !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00005105 return Error(Operands[2]->getStartLoc(),
5106 "registers must be in range r0-r7 or lr");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00005107 break;
5108 }
Jim Grosbachd80d1692011-08-23 18:15:37 +00005109 case ARM::tSTMIA_UPD: {
5110 bool listContainsBase;
Jim Grosbach099c9762011-09-16 20:50:13 +00005111 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachd80d1692011-08-23 18:15:37 +00005112 return Error(Operands[4]->getStartLoc(),
5113 "registers must be in range r0-r7");
5114 break;
5115 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005116 }
5117
5118 return false;
5119}
5120
Jim Grosbach2c590522011-12-20 20:46:29 +00005121static unsigned getRealVSTLNOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbacheb538222011-12-02 22:34:51 +00005122 switch(Opc) {
5123 default: assert(0 && "unexpected opcode!");
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005124 // VST1LN
5125 case ARM::VST1LNdWB_fixed_Asm_8: case ARM::VST1LNdWB_fixed_Asm_P8:
5126 case ARM::VST1LNdWB_fixed_Asm_I8: case ARM::VST1LNdWB_fixed_Asm_S8:
5127 case ARM::VST1LNdWB_fixed_Asm_U8:
Jim Grosbach2c590522011-12-20 20:46:29 +00005128 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005129 return ARM::VST1LNd8_UPD;
5130 case ARM::VST1LNdWB_fixed_Asm_16: case ARM::VST1LNdWB_fixed_Asm_P16:
5131 case ARM::VST1LNdWB_fixed_Asm_I16: case ARM::VST1LNdWB_fixed_Asm_S16:
5132 case ARM::VST1LNdWB_fixed_Asm_U16:
Jim Grosbach2c590522011-12-20 20:46:29 +00005133 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005134 return ARM::VST1LNd16_UPD;
5135 case ARM::VST1LNdWB_fixed_Asm_32: case ARM::VST1LNdWB_fixed_Asm_F:
5136 case ARM::VST1LNdWB_fixed_Asm_F32: case ARM::VST1LNdWB_fixed_Asm_I32:
5137 case ARM::VST1LNdWB_fixed_Asm_S32: case ARM::VST1LNdWB_fixed_Asm_U32:
Jim Grosbach2c590522011-12-20 20:46:29 +00005138 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005139 return ARM::VST1LNd32_UPD;
5140 case ARM::VST1LNdWB_register_Asm_8: case ARM::VST1LNdWB_register_Asm_P8:
5141 case ARM::VST1LNdWB_register_Asm_I8: case ARM::VST1LNdWB_register_Asm_S8:
5142 case ARM::VST1LNdWB_register_Asm_U8:
Jim Grosbach2c590522011-12-20 20:46:29 +00005143 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005144 return ARM::VST1LNd8_UPD;
5145 case ARM::VST1LNdWB_register_Asm_16: case ARM::VST1LNdWB_register_Asm_P16:
5146 case ARM::VST1LNdWB_register_Asm_I16: case ARM::VST1LNdWB_register_Asm_S16:
5147 case ARM::VST1LNdWB_register_Asm_U16:
Jim Grosbach2c590522011-12-20 20:46:29 +00005148 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005149 return ARM::VST1LNd16_UPD;
5150 case ARM::VST1LNdWB_register_Asm_32: case ARM::VST1LNdWB_register_Asm_F:
5151 case ARM::VST1LNdWB_register_Asm_F32: case ARM::VST1LNdWB_register_Asm_I32:
5152 case ARM::VST1LNdWB_register_Asm_S32: case ARM::VST1LNdWB_register_Asm_U32:
Jim Grosbach2c590522011-12-20 20:46:29 +00005153 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005154 return ARM::VST1LNd32_UPD;
5155 case ARM::VST1LNdAsm_8: case ARM::VST1LNdAsm_P8:
5156 case ARM::VST1LNdAsm_I8: case ARM::VST1LNdAsm_S8:
5157 case ARM::VST1LNdAsm_U8:
Jim Grosbach2c590522011-12-20 20:46:29 +00005158 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005159 return ARM::VST1LNd8;
5160 case ARM::VST1LNdAsm_16: case ARM::VST1LNdAsm_P16:
5161 case ARM::VST1LNdAsm_I16: case ARM::VST1LNdAsm_S16:
5162 case ARM::VST1LNdAsm_U16:
Jim Grosbach2c590522011-12-20 20:46:29 +00005163 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005164 return ARM::VST1LNd16;
5165 case ARM::VST1LNdAsm_32: case ARM::VST1LNdAsm_F:
5166 case ARM::VST1LNdAsm_F32: case ARM::VST1LNdAsm_I32:
5167 case ARM::VST1LNdAsm_S32: case ARM::VST1LNdAsm_U32:
Jim Grosbach2c590522011-12-20 20:46:29 +00005168 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005169 return ARM::VST1LNd32;
5170
5171 // VST2LN
5172 case ARM::VST2LNdWB_fixed_Asm_8: case ARM::VST2LNdWB_fixed_Asm_P8:
5173 case ARM::VST2LNdWB_fixed_Asm_I8: case ARM::VST2LNdWB_fixed_Asm_S8:
5174 case ARM::VST2LNdWB_fixed_Asm_U8:
Jim Grosbach2c590522011-12-20 20:46:29 +00005175 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005176 return ARM::VST2LNd8_UPD;
5177 case ARM::VST2LNdWB_fixed_Asm_16: case ARM::VST2LNdWB_fixed_Asm_P16:
5178 case ARM::VST2LNdWB_fixed_Asm_I16: case ARM::VST2LNdWB_fixed_Asm_S16:
5179 case ARM::VST2LNdWB_fixed_Asm_U16:
Jim Grosbach2c590522011-12-20 20:46:29 +00005180 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005181 return ARM::VST2LNd16_UPD;
5182 case ARM::VST2LNdWB_fixed_Asm_32: case ARM::VST2LNdWB_fixed_Asm_F:
5183 case ARM::VST2LNdWB_fixed_Asm_F32: case ARM::VST2LNdWB_fixed_Asm_I32:
5184 case ARM::VST2LNdWB_fixed_Asm_S32: case ARM::VST2LNdWB_fixed_Asm_U32:
Jim Grosbach2c590522011-12-20 20:46:29 +00005185 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005186 return ARM::VST2LNd32_UPD;
Jim Grosbach2c590522011-12-20 20:46:29 +00005187 case ARM::VST2LNqWB_fixed_Asm_16: case ARM::VST2LNqWB_fixed_Asm_P16:
5188 case ARM::VST2LNqWB_fixed_Asm_I16: case ARM::VST2LNqWB_fixed_Asm_S16:
5189 case ARM::VST2LNqWB_fixed_Asm_U16:
5190 Spacing = 2;
5191 return ARM::VST2LNq16_UPD;
5192 case ARM::VST2LNqWB_fixed_Asm_32: case ARM::VST2LNqWB_fixed_Asm_F:
5193 case ARM::VST2LNqWB_fixed_Asm_F32: case ARM::VST2LNqWB_fixed_Asm_I32:
5194 case ARM::VST2LNqWB_fixed_Asm_S32: case ARM::VST2LNqWB_fixed_Asm_U32:
5195 Spacing = 2;
5196 return ARM::VST2LNq32_UPD;
5197
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005198 case ARM::VST2LNdWB_register_Asm_8: case ARM::VST2LNdWB_register_Asm_P8:
5199 case ARM::VST2LNdWB_register_Asm_I8: case ARM::VST2LNdWB_register_Asm_S8:
5200 case ARM::VST2LNdWB_register_Asm_U8:
Jim Grosbach2c590522011-12-20 20:46:29 +00005201 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005202 return ARM::VST2LNd8_UPD;
5203 case ARM::VST2LNdWB_register_Asm_16: case ARM::VST2LNdWB_register_Asm_P16:
5204 case ARM::VST2LNdWB_register_Asm_I16: case ARM::VST2LNdWB_register_Asm_S16:
5205 case ARM::VST2LNdWB_register_Asm_U16:
Jim Grosbach2c590522011-12-20 20:46:29 +00005206 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005207 return ARM::VST2LNd16_UPD;
5208 case ARM::VST2LNdWB_register_Asm_32: case ARM::VST2LNdWB_register_Asm_F:
5209 case ARM::VST2LNdWB_register_Asm_F32: case ARM::VST2LNdWB_register_Asm_I32:
5210 case ARM::VST2LNdWB_register_Asm_S32: case ARM::VST2LNdWB_register_Asm_U32:
Jim Grosbach2c590522011-12-20 20:46:29 +00005211 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005212 return ARM::VST2LNd32_UPD;
Jim Grosbach2c590522011-12-20 20:46:29 +00005213 case ARM::VST2LNqWB_register_Asm_16: case ARM::VST2LNqWB_register_Asm_P16:
5214 case ARM::VST2LNqWB_register_Asm_I16: case ARM::VST2LNqWB_register_Asm_S16:
5215 case ARM::VST2LNqWB_register_Asm_U16:
5216 Spacing = 2;
5217 return ARM::VST2LNq16_UPD;
5218 case ARM::VST2LNqWB_register_Asm_32: case ARM::VST2LNqWB_register_Asm_F:
5219 case ARM::VST2LNqWB_register_Asm_F32: case ARM::VST2LNqWB_register_Asm_I32:
5220 case ARM::VST2LNqWB_register_Asm_S32: case ARM::VST2LNqWB_register_Asm_U32:
5221 Spacing = 2;
5222 return ARM::VST2LNq32_UPD;
5223
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005224 case ARM::VST2LNdAsm_8: case ARM::VST2LNdAsm_P8:
5225 case ARM::VST2LNdAsm_I8: case ARM::VST2LNdAsm_S8:
5226 case ARM::VST2LNdAsm_U8:
Jim Grosbach2c590522011-12-20 20:46:29 +00005227 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005228 return ARM::VST2LNd8;
5229 case ARM::VST2LNdAsm_16: case ARM::VST2LNdAsm_P16:
5230 case ARM::VST2LNdAsm_I16: case ARM::VST2LNdAsm_S16:
5231 case ARM::VST2LNdAsm_U16:
Jim Grosbach2c590522011-12-20 20:46:29 +00005232 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005233 return ARM::VST2LNd16;
5234 case ARM::VST2LNdAsm_32: case ARM::VST2LNdAsm_F:
5235 case ARM::VST2LNdAsm_F32: case ARM::VST2LNdAsm_I32:
5236 case ARM::VST2LNdAsm_S32: case ARM::VST2LNdAsm_U32:
Jim Grosbach2c590522011-12-20 20:46:29 +00005237 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005238 return ARM::VST2LNd32;
Jim Grosbach2c590522011-12-20 20:46:29 +00005239 case ARM::VST2LNqAsm_16: case ARM::VST2LNqAsm_P16:
5240 case ARM::VST2LNqAsm_I16: case ARM::VST2LNqAsm_S16:
5241 case ARM::VST2LNqAsm_U16:
5242 Spacing = 2;
5243 return ARM::VST2LNq16;
5244 case ARM::VST2LNqAsm_32: case ARM::VST2LNqAsm_F:
5245 case ARM::VST2LNqAsm_F32: case ARM::VST2LNqAsm_I32:
5246 case ARM::VST2LNqAsm_S32: case ARM::VST2LNqAsm_U32:
5247 Spacing = 2;
5248 return ARM::VST2LNq32;
Jim Grosbacheb538222011-12-02 22:34:51 +00005249 }
5250}
5251
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005252static unsigned getRealVLDLNOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach04945c42011-12-02 00:35:16 +00005253 switch(Opc) {
5254 default: assert(0 && "unexpected opcode!");
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005255 // VLD1LN
5256 case ARM::VLD1LNdWB_fixed_Asm_8: case ARM::VLD1LNdWB_fixed_Asm_P8:
5257 case ARM::VLD1LNdWB_fixed_Asm_I8: case ARM::VLD1LNdWB_fixed_Asm_S8:
5258 case ARM::VLD1LNdWB_fixed_Asm_U8:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005259 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005260 return ARM::VLD1LNd8_UPD;
5261 case ARM::VLD1LNdWB_fixed_Asm_16: case ARM::VLD1LNdWB_fixed_Asm_P16:
5262 case ARM::VLD1LNdWB_fixed_Asm_I16: case ARM::VLD1LNdWB_fixed_Asm_S16:
5263 case ARM::VLD1LNdWB_fixed_Asm_U16:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005264 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005265 return ARM::VLD1LNd16_UPD;
5266 case ARM::VLD1LNdWB_fixed_Asm_32: case ARM::VLD1LNdWB_fixed_Asm_F:
5267 case ARM::VLD1LNdWB_fixed_Asm_F32: case ARM::VLD1LNdWB_fixed_Asm_I32:
5268 case ARM::VLD1LNdWB_fixed_Asm_S32: case ARM::VLD1LNdWB_fixed_Asm_U32:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005269 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005270 return ARM::VLD1LNd32_UPD;
5271 case ARM::VLD1LNdWB_register_Asm_8: case ARM::VLD1LNdWB_register_Asm_P8:
5272 case ARM::VLD1LNdWB_register_Asm_I8: case ARM::VLD1LNdWB_register_Asm_S8:
5273 case ARM::VLD1LNdWB_register_Asm_U8:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005274 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005275 return ARM::VLD1LNd8_UPD;
5276 case ARM::VLD1LNdWB_register_Asm_16: case ARM::VLD1LNdWB_register_Asm_P16:
5277 case ARM::VLD1LNdWB_register_Asm_I16: case ARM::VLD1LNdWB_register_Asm_S16:
5278 case ARM::VLD1LNdWB_register_Asm_U16:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005279 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005280 return ARM::VLD1LNd16_UPD;
5281 case ARM::VLD1LNdWB_register_Asm_32: case ARM::VLD1LNdWB_register_Asm_F:
5282 case ARM::VLD1LNdWB_register_Asm_F32: case ARM::VLD1LNdWB_register_Asm_I32:
5283 case ARM::VLD1LNdWB_register_Asm_S32: case ARM::VLD1LNdWB_register_Asm_U32:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005284 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005285 return ARM::VLD1LNd32_UPD;
5286 case ARM::VLD1LNdAsm_8: case ARM::VLD1LNdAsm_P8:
5287 case ARM::VLD1LNdAsm_I8: case ARM::VLD1LNdAsm_S8:
5288 case ARM::VLD1LNdAsm_U8:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005289 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005290 return ARM::VLD1LNd8;
5291 case ARM::VLD1LNdAsm_16: case ARM::VLD1LNdAsm_P16:
5292 case ARM::VLD1LNdAsm_I16: case ARM::VLD1LNdAsm_S16:
5293 case ARM::VLD1LNdAsm_U16:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005294 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005295 return ARM::VLD1LNd16;
5296 case ARM::VLD1LNdAsm_32: case ARM::VLD1LNdAsm_F:
5297 case ARM::VLD1LNdAsm_F32: case ARM::VLD1LNdAsm_I32:
5298 case ARM::VLD1LNdAsm_S32: case ARM::VLD1LNdAsm_U32:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005299 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005300 return ARM::VLD1LNd32;
5301
5302 // VLD2LN
5303 case ARM::VLD2LNdWB_fixed_Asm_8: case ARM::VLD2LNdWB_fixed_Asm_P8:
5304 case ARM::VLD2LNdWB_fixed_Asm_I8: case ARM::VLD2LNdWB_fixed_Asm_S8:
5305 case ARM::VLD2LNdWB_fixed_Asm_U8:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005306 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005307 return ARM::VLD2LNd8_UPD;
5308 case ARM::VLD2LNdWB_fixed_Asm_16: case ARM::VLD2LNdWB_fixed_Asm_P16:
5309 case ARM::VLD2LNdWB_fixed_Asm_I16: case ARM::VLD2LNdWB_fixed_Asm_S16:
5310 case ARM::VLD2LNdWB_fixed_Asm_U16:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005311 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005312 return ARM::VLD2LNd16_UPD;
5313 case ARM::VLD2LNdWB_fixed_Asm_32: case ARM::VLD2LNdWB_fixed_Asm_F:
5314 case ARM::VLD2LNdWB_fixed_Asm_F32: case ARM::VLD2LNdWB_fixed_Asm_I32:
5315 case ARM::VLD2LNdWB_fixed_Asm_S32: case ARM::VLD2LNdWB_fixed_Asm_U32:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005316 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005317 return ARM::VLD2LNd32_UPD;
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005318 case ARM::VLD2LNqWB_fixed_Asm_16: case ARM::VLD2LNqWB_fixed_Asm_P16:
5319 case ARM::VLD2LNqWB_fixed_Asm_I16: case ARM::VLD2LNqWB_fixed_Asm_S16:
5320 case ARM::VLD2LNqWB_fixed_Asm_U16:
5321 Spacing = 1;
5322 return ARM::VLD2LNq16_UPD;
5323 case ARM::VLD2LNqWB_fixed_Asm_32: case ARM::VLD2LNqWB_fixed_Asm_F:
5324 case ARM::VLD2LNqWB_fixed_Asm_F32: case ARM::VLD2LNqWB_fixed_Asm_I32:
5325 case ARM::VLD2LNqWB_fixed_Asm_S32: case ARM::VLD2LNqWB_fixed_Asm_U32:
5326 Spacing = 2;
5327 return ARM::VLD2LNq32_UPD;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005328 case ARM::VLD2LNdWB_register_Asm_8: case ARM::VLD2LNdWB_register_Asm_P8:
5329 case ARM::VLD2LNdWB_register_Asm_I8: case ARM::VLD2LNdWB_register_Asm_S8:
5330 case ARM::VLD2LNdWB_register_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_register_Asm_16: case ARM::VLD2LNdWB_register_Asm_P16:
5334 case ARM::VLD2LNdWB_register_Asm_I16: case ARM::VLD2LNdWB_register_Asm_S16:
5335 case ARM::VLD2LNdWB_register_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_register_Asm_32: case ARM::VLD2LNdWB_register_Asm_F:
5339 case ARM::VLD2LNdWB_register_Asm_F32: case ARM::VLD2LNdWB_register_Asm_I32:
5340 case ARM::VLD2LNdWB_register_Asm_S32: case ARM::VLD2LNdWB_register_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_register_Asm_16: case ARM::VLD2LNqWB_register_Asm_P16:
5344 case ARM::VLD2LNqWB_register_Asm_I16: case ARM::VLD2LNqWB_register_Asm_S16:
5345 case ARM::VLD2LNqWB_register_Asm_U16:
5346 Spacing = 2;
5347 return ARM::VLD2LNq16_UPD;
5348 case ARM::VLD2LNqWB_register_Asm_32: case ARM::VLD2LNqWB_register_Asm_F:
5349 case ARM::VLD2LNqWB_register_Asm_F32: case ARM::VLD2LNqWB_register_Asm_I32:
5350 case ARM::VLD2LNqWB_register_Asm_S32: case ARM::VLD2LNqWB_register_Asm_U32:
5351 Spacing = 2;
5352 return ARM::VLD2LNq32_UPD;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005353 case ARM::VLD2LNdAsm_8: case ARM::VLD2LNdAsm_P8:
5354 case ARM::VLD2LNdAsm_I8: case ARM::VLD2LNdAsm_S8:
5355 case ARM::VLD2LNdAsm_U8:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005356 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005357 return ARM::VLD2LNd8;
5358 case ARM::VLD2LNdAsm_16: case ARM::VLD2LNdAsm_P16:
5359 case ARM::VLD2LNdAsm_I16: case ARM::VLD2LNdAsm_S16:
5360 case ARM::VLD2LNdAsm_U16:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005361 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005362 return ARM::VLD2LNd16;
5363 case ARM::VLD2LNdAsm_32: case ARM::VLD2LNdAsm_F:
5364 case ARM::VLD2LNdAsm_F32: case ARM::VLD2LNdAsm_I32:
5365 case ARM::VLD2LNdAsm_S32: case ARM::VLD2LNdAsm_U32:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005366 Spacing = 1;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005367 return ARM::VLD2LNd32;
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005368 case ARM::VLD2LNqAsm_16: case ARM::VLD2LNqAsm_P16:
5369 case ARM::VLD2LNqAsm_I16: case ARM::VLD2LNqAsm_S16:
5370 case ARM::VLD2LNqAsm_U16:
5371 Spacing = 2;
5372 return ARM::VLD2LNq16;
5373 case ARM::VLD2LNqAsm_32: case ARM::VLD2LNqAsm_F:
5374 case ARM::VLD2LNqAsm_F32: case ARM::VLD2LNqAsm_I32:
5375 case ARM::VLD2LNqAsm_S32: case ARM::VLD2LNqAsm_U32:
5376 Spacing = 2;
5377 return ARM::VLD2LNq32;
Jim Grosbach04945c42011-12-02 00:35:16 +00005378 }
5379}
5380
Jim Grosbachafad0532011-11-10 23:42:14 +00005381bool ARMAsmParser::
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005382processInstruction(MCInst &Inst,
5383 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5384 switch (Inst.getOpcode()) {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005385 // Handle NEON VST complex aliases.
5386 case ARM::VST1LNdWB_register_Asm_8: case ARM::VST1LNdWB_register_Asm_P8:
5387 case ARM::VST1LNdWB_register_Asm_I8: case ARM::VST1LNdWB_register_Asm_S8:
5388 case ARM::VST1LNdWB_register_Asm_U8: case ARM::VST1LNdWB_register_Asm_16:
5389 case ARM::VST1LNdWB_register_Asm_P16: case ARM::VST1LNdWB_register_Asm_I16:
5390 case ARM::VST1LNdWB_register_Asm_S16: case ARM::VST1LNdWB_register_Asm_U16:
5391 case ARM::VST1LNdWB_register_Asm_32: case ARM::VST1LNdWB_register_Asm_F:
5392 case ARM::VST1LNdWB_register_Asm_F32: case ARM::VST1LNdWB_register_Asm_I32:
5393 case ARM::VST1LNdWB_register_Asm_S32: case ARM::VST1LNdWB_register_Asm_U32: {
Jim Grosbacheb538222011-12-02 22:34:51 +00005394 MCInst TmpInst;
5395 // Shuffle the operands around so the lane index operand is in the
5396 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005397 unsigned Spacing;
5398 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacheb538222011-12-02 22:34:51 +00005399 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5400 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5401 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5402 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5403 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5404 TmpInst.addOperand(Inst.getOperand(1)); // lane
5405 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5406 TmpInst.addOperand(Inst.getOperand(6));
5407 Inst = TmpInst;
5408 return true;
5409 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005410
Jim Grosbach2c590522011-12-20 20:46:29 +00005411 case ARM::VST2LNdWB_register_Asm_8: case ARM::VST2LNdWB_register_Asm_P8:
5412 case ARM::VST2LNdWB_register_Asm_I8: case ARM::VST2LNdWB_register_Asm_S8:
5413 case ARM::VST2LNdWB_register_Asm_U8: case ARM::VST2LNdWB_register_Asm_16:
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005414 case ARM::VST2LNdWB_register_Asm_P16: case ARM::VST2LNdWB_register_Asm_I16:
5415 case ARM::VST2LNdWB_register_Asm_S16: case ARM::VST2LNdWB_register_Asm_U16:
Jim Grosbach2c590522011-12-20 20:46:29 +00005416 case ARM::VST2LNdWB_register_Asm_32: case ARM::VST2LNdWB_register_Asm_F:
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005417 case ARM::VST2LNdWB_register_Asm_F32: case ARM::VST2LNdWB_register_Asm_I32:
Jim Grosbach2c590522011-12-20 20:46:29 +00005418 case ARM::VST2LNdWB_register_Asm_S32: case ARM::VST2LNdWB_register_Asm_U32:
5419 case ARM::VST2LNqWB_register_Asm_16: case ARM::VST2LNqWB_register_Asm_P16:
5420 case ARM::VST2LNqWB_register_Asm_I16: case ARM::VST2LNqWB_register_Asm_S16:
5421 case ARM::VST2LNqWB_register_Asm_U16: case ARM::VST2LNqWB_register_Asm_32:
5422 case ARM::VST2LNqWB_register_Asm_F: case ARM::VST2LNqWB_register_Asm_F32:
5423 case ARM::VST2LNqWB_register_Asm_I32: case ARM::VST2LNqWB_register_Asm_S32:
5424 case ARM::VST2LNqWB_register_Asm_U32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005425 MCInst TmpInst;
5426 // Shuffle the operands around so the lane index operand is in the
5427 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005428 unsigned Spacing;
5429 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005430 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5431 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5432 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5433 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5434 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach2c590522011-12-20 20:46:29 +00005435 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5436 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005437 TmpInst.addOperand(Inst.getOperand(1)); // lane
5438 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5439 TmpInst.addOperand(Inst.getOperand(6));
5440 Inst = TmpInst;
5441 return true;
5442 }
5443 case ARM::VST1LNdWB_fixed_Asm_8: case ARM::VST1LNdWB_fixed_Asm_P8:
5444 case ARM::VST1LNdWB_fixed_Asm_I8: case ARM::VST1LNdWB_fixed_Asm_S8:
5445 case ARM::VST1LNdWB_fixed_Asm_U8: case ARM::VST1LNdWB_fixed_Asm_16:
5446 case ARM::VST1LNdWB_fixed_Asm_P16: case ARM::VST1LNdWB_fixed_Asm_I16:
5447 case ARM::VST1LNdWB_fixed_Asm_S16: case ARM::VST1LNdWB_fixed_Asm_U16:
5448 case ARM::VST1LNdWB_fixed_Asm_32: case ARM::VST1LNdWB_fixed_Asm_F:
5449 case ARM::VST1LNdWB_fixed_Asm_F32: case ARM::VST1LNdWB_fixed_Asm_I32:
5450 case ARM::VST1LNdWB_fixed_Asm_S32: case ARM::VST1LNdWB_fixed_Asm_U32: {
Jim Grosbacheb538222011-12-02 22:34:51 +00005451 MCInst TmpInst;
5452 // Shuffle the operands around so the lane index operand is in the
5453 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005454 unsigned Spacing;
5455 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacheb538222011-12-02 22:34:51 +00005456 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5457 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5458 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5459 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5460 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5461 TmpInst.addOperand(Inst.getOperand(1)); // lane
5462 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5463 TmpInst.addOperand(Inst.getOperand(5));
5464 Inst = TmpInst;
5465 return true;
5466 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005467
Jim Grosbach2c590522011-12-20 20:46:29 +00005468 case ARM::VST2LNdWB_fixed_Asm_8: case ARM::VST2LNdWB_fixed_Asm_P8:
5469 case ARM::VST2LNdWB_fixed_Asm_I8: case ARM::VST2LNdWB_fixed_Asm_S8:
5470 case ARM::VST2LNdWB_fixed_Asm_U8: case ARM::VST2LNdWB_fixed_Asm_16:
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005471 case ARM::VST2LNdWB_fixed_Asm_P16: case ARM::VST2LNdWB_fixed_Asm_I16:
5472 case ARM::VST2LNdWB_fixed_Asm_S16: case ARM::VST2LNdWB_fixed_Asm_U16:
Jim Grosbach2c590522011-12-20 20:46:29 +00005473 case ARM::VST2LNdWB_fixed_Asm_32: case ARM::VST2LNdWB_fixed_Asm_F:
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005474 case ARM::VST2LNdWB_fixed_Asm_F32: case ARM::VST2LNdWB_fixed_Asm_I32:
Jim Grosbach2c590522011-12-20 20:46:29 +00005475 case ARM::VST2LNdWB_fixed_Asm_S32: case ARM::VST2LNdWB_fixed_Asm_U32:
5476 case ARM::VST2LNqWB_fixed_Asm_16: case ARM::VST2LNqWB_fixed_Asm_P16:
5477 case ARM::VST2LNqWB_fixed_Asm_I16: case ARM::VST2LNqWB_fixed_Asm_S16:
5478 case ARM::VST2LNqWB_fixed_Asm_U16: case ARM::VST2LNqWB_fixed_Asm_32:
5479 case ARM::VST2LNqWB_fixed_Asm_F: case ARM::VST2LNqWB_fixed_Asm_F32:
5480 case ARM::VST2LNqWB_fixed_Asm_I32: case ARM::VST2LNqWB_fixed_Asm_S32:
5481 case ARM::VST2LNqWB_fixed_Asm_U32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005482 MCInst TmpInst;
5483 // Shuffle the operands around so the lane index operand is in the
5484 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005485 unsigned Spacing;
5486 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005487 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5488 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5489 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5490 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5491 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach2c590522011-12-20 20:46:29 +00005492 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5493 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005494 TmpInst.addOperand(Inst.getOperand(1)); // lane
5495 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5496 TmpInst.addOperand(Inst.getOperand(5));
5497 Inst = TmpInst;
5498 return true;
5499 }
5500 case ARM::VST1LNdAsm_8: case ARM::VST1LNdAsm_P8: case ARM::VST1LNdAsm_I8:
5501 case ARM::VST1LNdAsm_S8: case ARM::VST1LNdAsm_U8: case ARM::VST1LNdAsm_16:
5502 case ARM::VST1LNdAsm_P16: case ARM::VST1LNdAsm_I16: case ARM::VST1LNdAsm_S16:
5503 case ARM::VST1LNdAsm_U16: case ARM::VST1LNdAsm_32: case ARM::VST1LNdAsm_F:
5504 case ARM::VST1LNdAsm_F32: case ARM::VST1LNdAsm_I32: case ARM::VST1LNdAsm_S32:
Jim Grosbacheb538222011-12-02 22:34:51 +00005505 case ARM::VST1LNdAsm_U32: {
5506 MCInst TmpInst;
5507 // Shuffle the operands around so the lane index operand is in the
5508 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005509 unsigned Spacing;
5510 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacheb538222011-12-02 22:34:51 +00005511 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5512 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5513 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5514 TmpInst.addOperand(Inst.getOperand(1)); // lane
5515 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5516 TmpInst.addOperand(Inst.getOperand(5));
5517 Inst = TmpInst;
5518 return true;
5519 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005520
Jim Grosbach2c590522011-12-20 20:46:29 +00005521 case ARM::VST2LNdAsm_8: case ARM::VST2LNdAsm_P8: case ARM::VST2LNdAsm_I8:
5522 case ARM::VST2LNdAsm_S8: case ARM::VST2LNdAsm_U8: case ARM::VST2LNdAsm_16:
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005523 case ARM::VST2LNdAsm_P16: case ARM::VST2LNdAsm_I16: case ARM::VST2LNdAsm_S16:
Jim Grosbach2c590522011-12-20 20:46:29 +00005524 case ARM::VST2LNdAsm_U16: case ARM::VST2LNdAsm_32: case ARM::VST2LNdAsm_F:
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005525 case ARM::VST2LNdAsm_F32: case ARM::VST2LNdAsm_I32: case ARM::VST2LNdAsm_S32:
Jim Grosbach2c590522011-12-20 20:46:29 +00005526 case ARM::VST2LNdAsm_U32: case ARM::VST2LNqAsm_16: case ARM::VST2LNqAsm_P16:
5527 case ARM::VST2LNqAsm_I16: case ARM::VST2LNqAsm_S16: case ARM::VST2LNqAsm_U16:
5528 case ARM::VST2LNqAsm_32: case ARM::VST2LNqAsm_F: case ARM::VST2LNqAsm_F32:
5529 case ARM::VST2LNqAsm_I32: case ARM::VST2LNqAsm_S32: case ARM::VST2LNqAsm_U32:{
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005530 MCInst TmpInst;
5531 // Shuffle the operands around so the lane index operand is in the
5532 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00005533 unsigned Spacing;
5534 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005535 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5536 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5537 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach2c590522011-12-20 20:46:29 +00005538 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5539 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005540 TmpInst.addOperand(Inst.getOperand(1)); // lane
5541 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5542 TmpInst.addOperand(Inst.getOperand(5));
5543 Inst = TmpInst;
5544 return true;
5545 }
5546 // Handle NEON VLD complex aliases.
5547 case ARM::VLD1LNdWB_register_Asm_8: case ARM::VLD1LNdWB_register_Asm_P8:
5548 case ARM::VLD1LNdWB_register_Asm_I8: case ARM::VLD1LNdWB_register_Asm_S8:
5549 case ARM::VLD1LNdWB_register_Asm_U8: case ARM::VLD1LNdWB_register_Asm_16:
5550 case ARM::VLD1LNdWB_register_Asm_P16: case ARM::VLD1LNdWB_register_Asm_I16:
5551 case ARM::VLD1LNdWB_register_Asm_S16: case ARM::VLD1LNdWB_register_Asm_U16:
5552 case ARM::VLD1LNdWB_register_Asm_32: case ARM::VLD1LNdWB_register_Asm_F:
5553 case ARM::VLD1LNdWB_register_Asm_F32: case ARM::VLD1LNdWB_register_Asm_I32:
5554 case ARM::VLD1LNdWB_register_Asm_S32: case ARM::VLD1LNdWB_register_Asm_U32: {
Jim Grosbachdda976b2011-12-02 22:01:52 +00005555 MCInst TmpInst;
5556 // Shuffle the operands around so the lane index operand is in the
5557 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005558 unsigned Spacing;
5559 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachdda976b2011-12-02 22:01:52 +00005560 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5561 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5562 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5563 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5564 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5565 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5566 TmpInst.addOperand(Inst.getOperand(1)); // lane
5567 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5568 TmpInst.addOperand(Inst.getOperand(6));
5569 Inst = TmpInst;
5570 return true;
5571 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005572
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005573 case ARM::VLD2LNdWB_register_Asm_8: case ARM::VLD2LNdWB_register_Asm_P8:
5574 case ARM::VLD2LNdWB_register_Asm_I8: case ARM::VLD2LNdWB_register_Asm_S8:
5575 case ARM::VLD2LNdWB_register_Asm_U8: case ARM::VLD2LNdWB_register_Asm_16:
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005576 case ARM::VLD2LNdWB_register_Asm_P16: case ARM::VLD2LNdWB_register_Asm_I16:
5577 case ARM::VLD2LNdWB_register_Asm_S16: case ARM::VLD2LNdWB_register_Asm_U16:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005578 case ARM::VLD2LNdWB_register_Asm_32: case ARM::VLD2LNdWB_register_Asm_F:
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005579 case ARM::VLD2LNdWB_register_Asm_F32: case ARM::VLD2LNdWB_register_Asm_I32:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005580 case ARM::VLD2LNdWB_register_Asm_S32: case ARM::VLD2LNdWB_register_Asm_U32:
Jim Grosbach2c590522011-12-20 20:46:29 +00005581 case ARM::VLD2LNqWB_register_Asm_16: case ARM::VLD2LNqWB_register_Asm_P16:
5582 case ARM::VLD2LNqWB_register_Asm_I16: case ARM::VLD2LNqWB_register_Asm_S16:
5583 case ARM::VLD2LNqWB_register_Asm_U16: case ARM::VLD2LNqWB_register_Asm_32:
5584 case ARM::VLD2LNqWB_register_Asm_F: case ARM::VLD2LNqWB_register_Asm_F32:
5585 case ARM::VLD2LNqWB_register_Asm_I32: case ARM::VLD2LNqWB_register_Asm_S32:
5586 case ARM::VLD2LNqWB_register_Asm_U32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005587 MCInst TmpInst;
5588 // Shuffle the operands around so the lane index operand is in the
5589 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005590 unsigned Spacing;
5591 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005592 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005593 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5594 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005595 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5596 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5597 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5598 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5599 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005600 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5601 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005602 TmpInst.addOperand(Inst.getOperand(1)); // lane
5603 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5604 TmpInst.addOperand(Inst.getOperand(6));
5605 Inst = TmpInst;
5606 return true;
5607 }
5608
5609 case ARM::VLD1LNdWB_fixed_Asm_8: case ARM::VLD1LNdWB_fixed_Asm_P8:
5610 case ARM::VLD1LNdWB_fixed_Asm_I8: case ARM::VLD1LNdWB_fixed_Asm_S8:
5611 case ARM::VLD1LNdWB_fixed_Asm_U8: case ARM::VLD1LNdWB_fixed_Asm_16:
5612 case ARM::VLD1LNdWB_fixed_Asm_P16: case ARM::VLD1LNdWB_fixed_Asm_I16:
5613 case ARM::VLD1LNdWB_fixed_Asm_S16: case ARM::VLD1LNdWB_fixed_Asm_U16:
5614 case ARM::VLD1LNdWB_fixed_Asm_32: case ARM::VLD1LNdWB_fixed_Asm_F:
5615 case ARM::VLD1LNdWB_fixed_Asm_F32: case ARM::VLD1LNdWB_fixed_Asm_I32:
5616 case ARM::VLD1LNdWB_fixed_Asm_S32: case ARM::VLD1LNdWB_fixed_Asm_U32: {
Jim Grosbachdda976b2011-12-02 22:01:52 +00005617 MCInst TmpInst;
5618 // Shuffle the operands around so the lane index operand is in the
5619 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005620 unsigned Spacing;
5621 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachdda976b2011-12-02 22:01:52 +00005622 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5623 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5624 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5625 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5626 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5627 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5628 TmpInst.addOperand(Inst.getOperand(1)); // lane
5629 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5630 TmpInst.addOperand(Inst.getOperand(5));
5631 Inst = TmpInst;
5632 return true;
5633 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005634
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005635 case ARM::VLD2LNdWB_fixed_Asm_8: case ARM::VLD2LNdWB_fixed_Asm_P8:
5636 case ARM::VLD2LNdWB_fixed_Asm_I8: case ARM::VLD2LNdWB_fixed_Asm_S8:
5637 case ARM::VLD2LNdWB_fixed_Asm_U8: case ARM::VLD2LNdWB_fixed_Asm_16:
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005638 case ARM::VLD2LNdWB_fixed_Asm_P16: case ARM::VLD2LNdWB_fixed_Asm_I16:
5639 case ARM::VLD2LNdWB_fixed_Asm_S16: case ARM::VLD2LNdWB_fixed_Asm_U16:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005640 case ARM::VLD2LNdWB_fixed_Asm_32: case ARM::VLD2LNdWB_fixed_Asm_F:
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005641 case ARM::VLD2LNdWB_fixed_Asm_F32: case ARM::VLD2LNdWB_fixed_Asm_I32:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005642 case ARM::VLD2LNdWB_fixed_Asm_S32: case ARM::VLD2LNdWB_fixed_Asm_U32:
Jim Grosbach2c590522011-12-20 20:46:29 +00005643 case ARM::VLD2LNqWB_fixed_Asm_16: case ARM::VLD2LNqWB_fixed_Asm_P16:
5644 case ARM::VLD2LNqWB_fixed_Asm_I16: case ARM::VLD2LNqWB_fixed_Asm_S16:
5645 case ARM::VLD2LNqWB_fixed_Asm_U16: case ARM::VLD2LNqWB_fixed_Asm_32:
5646 case ARM::VLD2LNqWB_fixed_Asm_F: case ARM::VLD2LNqWB_fixed_Asm_F32:
5647 case ARM::VLD2LNqWB_fixed_Asm_I32: case ARM::VLD2LNqWB_fixed_Asm_S32:
5648 case ARM::VLD2LNqWB_fixed_Asm_U32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005649 MCInst TmpInst;
5650 // Shuffle the operands around so the lane index operand is in the
5651 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005652 unsigned Spacing;
5653 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005654 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005655 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5656 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005657 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5658 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5659 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5660 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5661 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005662 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5663 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005664 TmpInst.addOperand(Inst.getOperand(1)); // lane
5665 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5666 TmpInst.addOperand(Inst.getOperand(5));
5667 Inst = TmpInst;
5668 return true;
5669 }
5670
Jim Grosbach2c590522011-12-20 20:46:29 +00005671 case ARM::VLD1LNdAsm_8: case ARM::VLD1LNdAsm_P8: case ARM::VLD1LNdAsm_I8:
5672 case ARM::VLD1LNdAsm_S8: case ARM::VLD1LNdAsm_U8: case ARM::VLD1LNdAsm_16:
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005673 case ARM::VLD1LNdAsm_P16: case ARM::VLD1LNdAsm_I16: case ARM::VLD1LNdAsm_S16:
Jim Grosbach2c590522011-12-20 20:46:29 +00005674 case ARM::VLD1LNdAsm_U16: case ARM::VLD1LNdAsm_32: case ARM::VLD1LNdAsm_F:
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005675 case ARM::VLD1LNdAsm_F32: case ARM::VLD1LNdAsm_I32: case ARM::VLD1LNdAsm_S32:
Jim Grosbache7dcbc82011-12-02 18:52:30 +00005676 case ARM::VLD1LNdAsm_U32: {
Jim Grosbach04945c42011-12-02 00:35:16 +00005677 MCInst TmpInst;
5678 // Shuffle the operands around so the lane index operand is in the
5679 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005680 unsigned Spacing;
5681 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach04945c42011-12-02 00:35:16 +00005682 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5683 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5684 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5685 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5686 TmpInst.addOperand(Inst.getOperand(1)); // lane
5687 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5688 TmpInst.addOperand(Inst.getOperand(5));
5689 Inst = TmpInst;
5690 return true;
5691 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005692
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005693 case ARM::VLD2LNdAsm_8: case ARM::VLD2LNdAsm_P8: case ARM::VLD2LNdAsm_I8:
5694 case ARM::VLD2LNdAsm_S8: case ARM::VLD2LNdAsm_U8: case ARM::VLD2LNdAsm_16:
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005695 case ARM::VLD2LNdAsm_P16: case ARM::VLD2LNdAsm_I16: case ARM::VLD2LNdAsm_S16:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005696 case ARM::VLD2LNdAsm_U16: case ARM::VLD2LNdAsm_32: case ARM::VLD2LNdAsm_F:
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005697 case ARM::VLD2LNdAsm_F32: case ARM::VLD2LNdAsm_I32: case ARM::VLD2LNdAsm_S32:
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005698 case ARM::VLD2LNdAsm_U32: case ARM::VLD2LNqAsm_16: case ARM::VLD2LNqAsm_P16:
5699 case ARM::VLD2LNqAsm_I16: case ARM::VLD2LNqAsm_S16: case ARM::VLD2LNqAsm_U16:
5700 case ARM::VLD2LNqAsm_32: case ARM::VLD2LNqAsm_F: case ARM::VLD2LNqAsm_F32:
5701 case ARM::VLD2LNqAsm_I32: case ARM::VLD2LNqAsm_S32:
5702 case ARM::VLD2LNqAsm_U32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005703 MCInst TmpInst;
5704 // Shuffle the operands around so the lane index operand is in the
5705 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005706 unsigned Spacing;
5707 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005708 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005709 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5710 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005711 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5712 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5713 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach75e2ab52011-12-20 19:21:26 +00005714 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5715 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005716 TmpInst.addOperand(Inst.getOperand(1)); // lane
5717 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5718 TmpInst.addOperand(Inst.getOperand(5));
5719 Inst = TmpInst;
5720 return true;
5721 }
Jim Grosbach485e5622011-12-13 22:45:11 +00005722 // Handle the Thumb2 mode MOV complex aliases.
5723 case ARM::t2MOVsi:
5724 case ARM::t2MOVSsi: {
5725 // Which instruction to expand to depends on the CCOut operand and
5726 // whether we're in an IT block if the register operands are low
5727 // registers.
5728 bool isNarrow = false;
5729 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5730 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5731 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
5732 isNarrow = true;
5733 MCInst TmpInst;
5734 unsigned newOpc;
5735 switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
5736 default: llvm_unreachable("unexpected opcode!");
5737 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
5738 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
5739 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
5740 case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
5741 }
5742 unsigned Ammount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
5743 if (Ammount == 32) Ammount = 0;
5744 TmpInst.setOpcode(newOpc);
5745 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5746 if (isNarrow)
5747 TmpInst.addOperand(MCOperand::CreateReg(
5748 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
5749 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5750 TmpInst.addOperand(MCOperand::CreateImm(Ammount));
5751 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5752 TmpInst.addOperand(Inst.getOperand(4));
5753 if (!isNarrow)
5754 TmpInst.addOperand(MCOperand::CreateReg(
5755 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
5756 Inst = TmpInst;
5757 return true;
5758 }
5759 // Handle the ARM mode MOV complex aliases.
Jim Grosbachabcac562011-11-16 18:31:45 +00005760 case ARM::ASRr:
5761 case ARM::LSRr:
5762 case ARM::LSLr:
5763 case ARM::RORr: {
5764 ARM_AM::ShiftOpc ShiftTy;
5765 switch(Inst.getOpcode()) {
5766 default: llvm_unreachable("unexpected opcode!");
5767 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
5768 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
5769 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
5770 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
5771 }
5772 // A shift by zero is a plain MOVr, not a MOVsi.
5773 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
5774 MCInst TmpInst;
5775 TmpInst.setOpcode(ARM::MOVsr);
5776 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5777 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5778 TmpInst.addOperand(Inst.getOperand(2)); // Rm
5779 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5780 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5781 TmpInst.addOperand(Inst.getOperand(4));
5782 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5783 Inst = TmpInst;
5784 return true;
5785 }
Jim Grosbachc14871c2011-11-10 19:18:01 +00005786 case ARM::ASRi:
5787 case ARM::LSRi:
5788 case ARM::LSLi:
5789 case ARM::RORi: {
5790 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachc14871c2011-11-10 19:18:01 +00005791 switch(Inst.getOpcode()) {
5792 default: llvm_unreachable("unexpected opcode!");
5793 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
5794 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
5795 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
5796 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
5797 }
5798 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach1a2f9ee2011-11-16 19:05:59 +00005799 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachc14871c2011-11-10 19:18:01 +00005800 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
5801 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach61db5a52011-11-10 16:44:55 +00005802 MCInst TmpInst;
Jim Grosbachc14871c2011-11-10 19:18:01 +00005803 TmpInst.setOpcode(Opc);
Jim Grosbach61db5a52011-11-10 16:44:55 +00005804 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5805 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachc14871c2011-11-10 19:18:01 +00005806 if (Opc == ARM::MOVsi)
5807 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach61db5a52011-11-10 16:44:55 +00005808 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5809 TmpInst.addOperand(Inst.getOperand(4));
5810 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5811 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00005812 return true;
Jim Grosbach61db5a52011-11-10 16:44:55 +00005813 }
Jim Grosbach1a2f9ee2011-11-16 19:05:59 +00005814 case ARM::RRXi: {
5815 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
5816 MCInst TmpInst;
5817 TmpInst.setOpcode(ARM::MOVsi);
5818 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5819 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5820 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5821 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5822 TmpInst.addOperand(Inst.getOperand(3));
5823 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
5824 Inst = TmpInst;
5825 return true;
5826 }
Jim Grosbachd9a9be22011-11-10 23:58:34 +00005827 case ARM::t2LDMIA_UPD: {
5828 // If this is a load of a single register, then we should use
5829 // a post-indexed LDR instruction instead, per the ARM ARM.
5830 if (Inst.getNumOperands() != 5)
5831 return false;
5832 MCInst TmpInst;
5833 TmpInst.setOpcode(ARM::t2LDR_POST);
5834 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5835 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5836 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5837 TmpInst.addOperand(MCOperand::CreateImm(4));
5838 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5839 TmpInst.addOperand(Inst.getOperand(3));
5840 Inst = TmpInst;
5841 return true;
5842 }
5843 case ARM::t2STMDB_UPD: {
5844 // If this is a store of a single register, then we should use
5845 // a pre-indexed STR instruction instead, per the ARM ARM.
5846 if (Inst.getNumOperands() != 5)
5847 return false;
5848 MCInst TmpInst;
5849 TmpInst.setOpcode(ARM::t2STR_PRE);
5850 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5851 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5852 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5853 TmpInst.addOperand(MCOperand::CreateImm(-4));
5854 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5855 TmpInst.addOperand(Inst.getOperand(3));
5856 Inst = TmpInst;
5857 return true;
5858 }
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005859 case ARM::LDMIA_UPD:
5860 // If this is a load of a single register via a 'pop', then we should use
5861 // a post-indexed LDR instruction instead, per the ARM ARM.
5862 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
5863 Inst.getNumOperands() == 5) {
5864 MCInst TmpInst;
5865 TmpInst.setOpcode(ARM::LDR_POST_IMM);
5866 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5867 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5868 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5869 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
5870 TmpInst.addOperand(MCOperand::CreateImm(4));
5871 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5872 TmpInst.addOperand(Inst.getOperand(3));
5873 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00005874 return true;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005875 }
5876 break;
Jim Grosbach27ad83d2011-08-11 18:07:11 +00005877 case ARM::STMDB_UPD:
5878 // If this is a store of a single register via a 'push', then we should use
5879 // a pre-indexed STR instruction instead, per the ARM ARM.
5880 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
5881 Inst.getNumOperands() == 5) {
5882 MCInst TmpInst;
5883 TmpInst.setOpcode(ARM::STR_PRE_IMM);
5884 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5885 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5886 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
5887 TmpInst.addOperand(MCOperand::CreateImm(-4));
5888 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5889 TmpInst.addOperand(Inst.getOperand(3));
5890 Inst = TmpInst;
5891 }
5892 break;
Jim Grosbachec9ba982011-12-05 21:06:26 +00005893 case ARM::t2ADDri12:
5894 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
5895 // mnemonic was used (not "addw"), encoding T3 is preferred.
5896 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
5897 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5898 break;
5899 Inst.setOpcode(ARM::t2ADDri);
5900 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5901 break;
5902 case ARM::t2SUBri12:
5903 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
5904 // mnemonic was used (not "subw"), encoding T3 is preferred.
5905 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
5906 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5907 break;
5908 Inst.setOpcode(ARM::t2SUBri);
5909 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5910 break;
Jim Grosbache9ab47a2011-08-16 23:57:34 +00005911 case ARM::tADDi8:
Jim Grosbach6d606fb2011-08-31 17:07:33 +00005912 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5913 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5914 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5915 // to encoding T1 if <Rd> is omitted."
Jim Grosbachafad0532011-11-10 23:42:14 +00005916 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbache9ab47a2011-08-16 23:57:34 +00005917 Inst.setOpcode(ARM::tADDi3);
Jim Grosbachafad0532011-11-10 23:42:14 +00005918 return true;
5919 }
Jim Grosbache9ab47a2011-08-16 23:57:34 +00005920 break;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00005921 case ARM::tSUBi8:
5922 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5923 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5924 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5925 // to encoding T1 if <Rd> is omitted."
Jim Grosbachafad0532011-11-10 23:42:14 +00005926 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachd0c435c2011-09-16 22:58:42 +00005927 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbachafad0532011-11-10 23:42:14 +00005928 return true;
5929 }
Jim Grosbachd0c435c2011-09-16 22:58:42 +00005930 break;
Jim Grosbache489bab2011-12-05 22:16:39 +00005931 case ARM::t2ADDrr: {
5932 // If the destination and first source operand are the same, and
5933 // there's no setting of the flags, use encoding T2 instead of T3.
5934 // Note that this is only for ADD, not SUB. This mirrors the system
5935 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
5936 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
5937 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbachb8c719c2011-12-05 22:27:04 +00005938 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5939 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbache489bab2011-12-05 22:16:39 +00005940 break;
5941 MCInst TmpInst;
5942 TmpInst.setOpcode(ARM::tADDhirr);
5943 TmpInst.addOperand(Inst.getOperand(0));
5944 TmpInst.addOperand(Inst.getOperand(0));
5945 TmpInst.addOperand(Inst.getOperand(2));
5946 TmpInst.addOperand(Inst.getOperand(3));
5947 TmpInst.addOperand(Inst.getOperand(4));
5948 Inst = TmpInst;
5949 return true;
5950 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00005951 case ARM::tB:
5952 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbachafad0532011-11-10 23:42:14 +00005953 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson29cfe6c2011-09-09 21:48:23 +00005954 Inst.setOpcode(ARM::tBcc);
Jim Grosbachafad0532011-11-10 23:42:14 +00005955 return true;
5956 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00005957 break;
5958 case ARM::t2B:
5959 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbachafad0532011-11-10 23:42:14 +00005960 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson29cfe6c2011-09-09 21:48:23 +00005961 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbachafad0532011-11-10 23:42:14 +00005962 return true;
5963 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00005964 break;
Jim Grosbach99bc8462011-08-31 21:17:31 +00005965 case ARM::t2Bcc:
Jim Grosbacha0d34d32011-09-02 23:22:08 +00005966 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbachafad0532011-11-10 23:42:14 +00005967 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbach99bc8462011-08-31 21:17:31 +00005968 Inst.setOpcode(ARM::t2B);
Jim Grosbachafad0532011-11-10 23:42:14 +00005969 return true;
5970 }
Jim Grosbach99bc8462011-08-31 21:17:31 +00005971 break;
Jim Grosbachcbd4ab12011-08-17 22:57:40 +00005972 case ARM::tBcc:
5973 // If the conditional is AL, we really want tB.
Jim Grosbachafad0532011-11-10 23:42:14 +00005974 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbachcbd4ab12011-08-17 22:57:40 +00005975 Inst.setOpcode(ARM::tB);
Jim Grosbachafad0532011-11-10 23:42:14 +00005976 return true;
5977 }
Jim Grosbach6ddb5682011-08-18 16:08:39 +00005978 break;
Jim Grosbacha31f2232011-09-07 18:05:34 +00005979 case ARM::tLDMIA: {
5980 // If the register list contains any high registers, or if the writeback
5981 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
5982 // instead if we're in Thumb2. Otherwise, this should have generated
5983 // an error in validateInstruction().
5984 unsigned Rn = Inst.getOperand(0).getReg();
5985 bool hasWritebackToken =
5986 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5987 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
5988 bool listContainsBase;
5989 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
5990 (!listContainsBase && !hasWritebackToken) ||
5991 (listContainsBase && hasWritebackToken)) {
5992 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
5993 assert (isThumbTwo());
5994 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
5995 // If we're switching to the updating version, we need to insert
5996 // the writeback tied operand.
5997 if (hasWritebackToken)
5998 Inst.insert(Inst.begin(),
5999 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbachafad0532011-11-10 23:42:14 +00006000 return true;
Jim Grosbacha31f2232011-09-07 18:05:34 +00006001 }
6002 break;
6003 }
Jim Grosbach099c9762011-09-16 20:50:13 +00006004 case ARM::tSTMIA_UPD: {
6005 // If the register list contains any high registers, we need to use
6006 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6007 // should have generated an error in validateInstruction().
6008 unsigned Rn = Inst.getOperand(0).getReg();
6009 bool listContainsBase;
6010 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
6011 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6012 assert (isThumbTwo());
6013 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbachafad0532011-11-10 23:42:14 +00006014 return true;
Jim Grosbach099c9762011-09-16 20:50:13 +00006015 }
6016 break;
6017 }
Jim Grosbach9bded9d2011-11-10 23:17:11 +00006018 case ARM::tPOP: {
6019 bool listContainsBase;
6020 // If the register list contains any high registers, we need to use
6021 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6022 // should have generated an error in validateInstruction().
6023 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbachafad0532011-11-10 23:42:14 +00006024 return false;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00006025 assert (isThumbTwo());
6026 Inst.setOpcode(ARM::t2LDMIA_UPD);
6027 // Add the base register and writeback operands.
6028 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6029 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbachafad0532011-11-10 23:42:14 +00006030 return true;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00006031 }
6032 case ARM::tPUSH: {
6033 bool listContainsBase;
6034 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbachafad0532011-11-10 23:42:14 +00006035 return false;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00006036 assert (isThumbTwo());
6037 Inst.setOpcode(ARM::t2STMDB_UPD);
6038 // Add the base register and writeback operands.
6039 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6040 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbachafad0532011-11-10 23:42:14 +00006041 return true;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00006042 }
Jim Grosbachb908b7a2011-09-10 00:15:36 +00006043 case ARM::t2MOVi: {
6044 // If we can use the 16-bit encoding and the user didn't explicitly
6045 // request the 32-bit variant, transform it here.
6046 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6047 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbach18b8b172011-09-14 19:12:11 +00006048 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
6049 Inst.getOperand(4).getReg() == ARM::CPSR) ||
6050 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbachb908b7a2011-09-10 00:15:36 +00006051 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6052 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6053 // The operands aren't in the same order for tMOVi8...
6054 MCInst TmpInst;
6055 TmpInst.setOpcode(ARM::tMOVi8);
6056 TmpInst.addOperand(Inst.getOperand(0));
6057 TmpInst.addOperand(Inst.getOperand(4));
6058 TmpInst.addOperand(Inst.getOperand(1));
6059 TmpInst.addOperand(Inst.getOperand(2));
6060 TmpInst.addOperand(Inst.getOperand(3));
6061 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00006062 return true;
Jim Grosbachb908b7a2011-09-10 00:15:36 +00006063 }
6064 break;
6065 }
6066 case ARM::t2MOVr: {
6067 // If we can use the 16-bit encoding and the user didn't explicitly
6068 // request the 32-bit variant, transform it here.
6069 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6070 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6071 Inst.getOperand(2).getImm() == ARMCC::AL &&
6072 Inst.getOperand(4).getReg() == ARM::CPSR &&
6073 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6074 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6075 // The operands aren't the same for tMOV[S]r... (no cc_out)
6076 MCInst TmpInst;
6077 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
6078 TmpInst.addOperand(Inst.getOperand(0));
6079 TmpInst.addOperand(Inst.getOperand(1));
6080 TmpInst.addOperand(Inst.getOperand(2));
6081 TmpInst.addOperand(Inst.getOperand(3));
6082 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00006083 return true;
Jim Grosbachb908b7a2011-09-10 00:15:36 +00006084 }
6085 break;
6086 }
Jim Grosbach82213192011-09-19 20:29:33 +00006087 case ARM::t2SXTH:
Jim Grosbachb3519802011-09-20 00:46:54 +00006088 case ARM::t2SXTB:
6089 case ARM::t2UXTH:
6090 case ARM::t2UXTB: {
Jim Grosbach82213192011-09-19 20:29:33 +00006091 // If we can use the 16-bit encoding and the user didn't explicitly
6092 // request the 32-bit variant, transform it here.
6093 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6094 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6095 Inst.getOperand(2).getImm() == 0 &&
6096 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6097 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbachb3519802011-09-20 00:46:54 +00006098 unsigned NewOpc;
6099 switch (Inst.getOpcode()) {
6100 default: llvm_unreachable("Illegal opcode!");
6101 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
6102 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
6103 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
6104 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
6105 }
Jim Grosbach82213192011-09-19 20:29:33 +00006106 // The operands aren't the same for thumb1 (no rotate operand).
6107 MCInst TmpInst;
6108 TmpInst.setOpcode(NewOpc);
6109 TmpInst.addOperand(Inst.getOperand(0));
6110 TmpInst.addOperand(Inst.getOperand(1));
6111 TmpInst.addOperand(Inst.getOperand(3));
6112 TmpInst.addOperand(Inst.getOperand(4));
6113 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00006114 return true;
Jim Grosbach82213192011-09-19 20:29:33 +00006115 }
6116 break;
6117 }
Jim Grosbache2ca9e52011-12-20 00:59:38 +00006118 case ARM::MOVsi: {
6119 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm());
6120 if (SOpc == ARM_AM::rrx) return false;
6121 if (ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()) == 0) {
6122 // Shifting by zero is accepted as a vanilla 'MOVr'
6123 MCInst TmpInst;
6124 TmpInst.setOpcode(ARM::MOVr);
6125 TmpInst.addOperand(Inst.getOperand(0));
6126 TmpInst.addOperand(Inst.getOperand(1));
6127 TmpInst.addOperand(Inst.getOperand(3));
6128 TmpInst.addOperand(Inst.getOperand(4));
6129 TmpInst.addOperand(Inst.getOperand(5));
6130 Inst = TmpInst;
6131 return true;
6132 }
6133 return false;
6134 }
Jim Grosbach3d1eac82011-08-26 21:43:41 +00006135 case ARM::t2IT: {
6136 // The mask bits for all but the first condition are represented as
6137 // the low bit of the condition code value implies 't'. We currently
6138 // always have 1 implies 't', so XOR toggle the bits if the low bit
6139 // of the condition code is zero. The encoding also expects the low
6140 // bit of the condition to be encoded as bit 4 of the mask operand,
6141 // so mask that in if needed
6142 MCOperand &MO = Inst.getOperand(1);
6143 unsigned Mask = MO.getImm();
Jim Grosbached16ec42011-08-29 22:24:09 +00006144 unsigned OrigMask = Mask;
6145 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00006146 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach3d1eac82011-08-26 21:43:41 +00006147 assert(Mask && TZ <= 3 && "illegal IT mask value!");
6148 for (unsigned i = 3; i != TZ; --i)
6149 Mask ^= 1 << i;
6150 } else
6151 Mask |= 0x10;
6152 MO.setImm(Mask);
Jim Grosbached16ec42011-08-29 22:24:09 +00006153
6154 // Set up the IT block state according to the IT instruction we just
6155 // matched.
6156 assert(!inITBlock() && "nested IT blocks?!");
6157 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
6158 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
6159 ITState.CurPosition = 0;
6160 ITState.FirstCond = true;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00006161 break;
6162 }
Jim Grosbach8ba76c62011-08-11 17:35:48 +00006163 }
Jim Grosbachafad0532011-11-10 23:42:14 +00006164 return false;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00006165}
6166
Jim Grosbach3e941ae2011-08-16 20:45:50 +00006167unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
6168 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
6169 // suffix depending on whether they're in an IT block or not.
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00006170 unsigned Opc = Inst.getOpcode();
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00006171 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach3e941ae2011-08-16 20:45:50 +00006172 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
6173 assert(MCID.hasOptionalDef() &&
6174 "optionally flag setting instruction missing optional def operand");
6175 assert(MCID.NumOperands == Inst.getNumOperands() &&
6176 "operand count mismatch!");
6177 // Find the optional-def operand (cc_out).
6178 unsigned OpNo;
6179 for (OpNo = 0;
6180 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
6181 ++OpNo)
6182 ;
6183 // If we're parsing Thumb1, reject it completely.
6184 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
6185 return Match_MnemonicFail;
6186 // If we're parsing Thumb2, which form is legal depends on whether we're
6187 // in an IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00006188 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
6189 !inITBlock())
Jim Grosbach3e941ae2011-08-16 20:45:50 +00006190 return Match_RequiresITBlock;
Jim Grosbached16ec42011-08-29 22:24:09 +00006191 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
6192 inITBlock())
6193 return Match_RequiresNotITBlock;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00006194 }
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00006195 // Some high-register supporting Thumb1 encodings only allow both registers
6196 // to be from r0-r7 when in Thumb2.
6197 else if (Opc == ARM::tADDhirr && isThumbOne() &&
6198 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6199 isARMLowRegister(Inst.getOperand(2).getReg()))
6200 return Match_RequiresThumb2;
6201 // Others only require ARMv6 or later.
Jim Grosbachf86cd372011-08-19 20:46:54 +00006202 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00006203 isARMLowRegister(Inst.getOperand(0).getReg()) &&
6204 isARMLowRegister(Inst.getOperand(1).getReg()))
6205 return Match_RequiresV6;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00006206 return Match_Success;
6207}
6208
Chris Lattner9487de62010-10-28 21:28:01 +00006209bool ARMAsmParser::
6210MatchAndEmitInstruction(SMLoc IDLoc,
6211 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
6212 MCStreamer &Out) {
6213 MCInst Inst;
6214 unsigned ErrorInfo;
Jim Grosbach120a96a2011-08-15 23:03:29 +00006215 unsigned MatchResult;
Kevin Enderby3164a342010-12-09 19:19:43 +00006216 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby3164a342010-12-09 19:19:43 +00006217 switch (MatchResult) {
Jim Grosbach120a96a2011-08-15 23:03:29 +00006218 default: break;
Chris Lattnerd27b05e2010-10-28 21:41:58 +00006219 case Match_Success:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00006220 // Context sensitive operand constraints aren't handled by the matcher,
6221 // so check them here.
Jim Grosbacha0d34d32011-09-02 23:22:08 +00006222 if (validateInstruction(Inst, Operands)) {
6223 // Still progress the IT block, otherwise one wrong condition causes
6224 // nasty cascading errors.
6225 forwardITPosition();
Jim Grosbachedaa35a2011-07-26 18:25:39 +00006226 return true;
Jim Grosbacha0d34d32011-09-02 23:22:08 +00006227 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00006228
Jim Grosbach8ba76c62011-08-11 17:35:48 +00006229 // Some instructions need post-processing to, for example, tweak which
Jim Grosbachafad0532011-11-10 23:42:14 +00006230 // encoding is selected. Loop on it while changes happen so the
6231 // individual transformations can chain off each other. E.g.,
6232 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
6233 while (processInstruction(Inst, Operands))
6234 ;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00006235
Jim Grosbacha0d34d32011-09-02 23:22:08 +00006236 // Only move forward at the very end so that everything in validate
6237 // and process gets a consistent answer about whether we're in an IT
6238 // block.
6239 forwardITPosition();
6240
Chris Lattner9487de62010-10-28 21:28:01 +00006241 Out.EmitInstruction(Inst);
6242 return false;
Chris Lattnerd27b05e2010-10-28 21:41:58 +00006243 case Match_MissingFeature:
6244 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
6245 return true;
6246 case Match_InvalidOperand: {
6247 SMLoc ErrorLoc = IDLoc;
6248 if (ErrorInfo != ~0U) {
6249 if (ErrorInfo >= Operands.size())
6250 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach624bcc72010-10-29 14:46:02 +00006251
Chris Lattnerd27b05e2010-10-28 21:41:58 +00006252 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
6253 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
6254 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00006255
Chris Lattnerd27b05e2010-10-28 21:41:58 +00006256 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattner9487de62010-10-28 21:28:01 +00006257 }
Chris Lattnerd27b05e2010-10-28 21:41:58 +00006258 case Match_MnemonicFail:
Jim Grosbach3e941ae2011-08-16 20:45:50 +00006259 return Error(IDLoc, "invalid instruction");
Daniel Dunbar66193402011-02-04 17:12:23 +00006260 case Match_ConversionFail:
Jim Grosbach8e048492011-08-19 22:07:46 +00006261 // The converter function will have already emited a diagnostic.
6262 return true;
Jim Grosbached16ec42011-08-29 22:24:09 +00006263 case Match_RequiresNotITBlock:
6264 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach3e941ae2011-08-16 20:45:50 +00006265 case Match_RequiresITBlock:
6266 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00006267 case Match_RequiresV6:
6268 return Error(IDLoc, "instruction variant requires ARMv6 or later");
6269 case Match_RequiresThumb2:
6270 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnerd27b05e2010-10-28 21:41:58 +00006271 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00006272
Eric Christopher91d7b902010-10-29 09:26:59 +00006273 llvm_unreachable("Implement any new match types added!");
Bill Wendlingee7f1f92010-11-06 21:42:12 +00006274 return true;
Chris Lattner9487de62010-10-28 21:28:01 +00006275}
6276
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006277/// parseDirective parses the arm specific directives
Kevin Enderbyccab3172009-09-15 00:27:25 +00006278bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
6279 StringRef IDVal = DirectiveID.getIdentifier();
6280 if (IDVal == ".word")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006281 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00006282 else if (IDVal == ".thumb")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006283 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach7f882392011-12-07 18:04:19 +00006284 else if (IDVal == ".arm")
6285 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00006286 else if (IDVal == ".thumb_func")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006287 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00006288 else if (IDVal == ".code")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006289 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00006290 else if (IDVal == ".syntax")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006291 return parseDirectiveSyntax(DirectiveID.getLoc());
Jim Grosbachab5830e2011-12-14 02:16:11 +00006292 else if (IDVal == ".unreq")
6293 return parseDirectiveUnreq(DirectiveID.getLoc());
Jason W Kim135d2442011-12-20 17:38:12 +00006294 else if (IDVal == ".arch")
6295 return parseDirectiveArch(DirectiveID.getLoc());
6296 else if (IDVal == ".eabi_attribute")
6297 return parseDirectiveEabiAttr(DirectiveID.getLoc());
Kevin Enderbyccab3172009-09-15 00:27:25 +00006298 return true;
6299}
6300
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006301/// parseDirectiveWord
Kevin Enderbyccab3172009-09-15 00:27:25 +00006302/// ::= .word [ expression (, expression)* ]
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006303bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyccab3172009-09-15 00:27:25 +00006304 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6305 for (;;) {
6306 const MCExpr *Value;
6307 if (getParser().ParseExpression(Value))
6308 return true;
6309
Chris Lattnerc35681b2010-01-19 19:46:13 +00006310 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyccab3172009-09-15 00:27:25 +00006311
6312 if (getLexer().is(AsmToken::EndOfStatement))
6313 break;
Jim Grosbach624bcc72010-10-29 14:46:02 +00006314
Kevin Enderbyccab3172009-09-15 00:27:25 +00006315 // FIXME: Improve diagnostic.
6316 if (getLexer().isNot(AsmToken::Comma))
6317 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00006318 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00006319 }
6320 }
6321
Sean Callanana83fd7d2010-01-19 20:27:46 +00006322 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00006323 return false;
6324}
6325
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006326/// parseDirectiveThumb
Kevin Enderby146dcf22009-10-15 20:48:48 +00006327/// ::= .thumb
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006328bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby146dcf22009-10-15 20:48:48 +00006329 if (getLexer().isNot(AsmToken::EndOfStatement))
6330 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00006331 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006332
Jim Grosbach7f882392011-12-07 18:04:19 +00006333 if (!isThumb())
6334 SwitchMode();
6335 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
6336 return false;
6337}
6338
6339/// parseDirectiveARM
6340/// ::= .arm
6341bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
6342 if (getLexer().isNot(AsmToken::EndOfStatement))
6343 return Error(L, "unexpected token in directive");
6344 Parser.Lex();
6345
6346 if (isThumb())
6347 SwitchMode();
6348 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby146dcf22009-10-15 20:48:48 +00006349 return false;
6350}
6351
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006352/// parseDirectiveThumbFunc
Kevin Enderby146dcf22009-10-15 20:48:48 +00006353/// ::= .thumbfunc symbol_name
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006354bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00006355 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
6356 bool isMachO = MAI.hasSubsectionsViaSymbols();
6357 StringRef Name;
6358
6359 // Darwin asm has function name after .thumb_func direction
6360 // ELF doesn't
6361 if (isMachO) {
6362 const AsmToken &Tok = Parser.getTok();
6363 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
6364 return Error(L, "unexpected token in .thumb_func directive");
Jim Grosbach42ba6282011-11-10 20:48:53 +00006365 Name = Tok.getIdentifier();
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00006366 Parser.Lex(); // Consume the identifier token.
6367 }
6368
Jim Grosbach42ba6282011-11-10 20:48:53 +00006369 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby146dcf22009-10-15 20:48:48 +00006370 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00006371 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006372
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00006373 // FIXME: assuming function name will be the line following .thumb_func
6374 if (!isMachO) {
Jim Grosbach42ba6282011-11-10 20:48:53 +00006375 Name = Parser.getTok().getIdentifier();
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00006376 }
6377
Jim Grosbachc6db8ce2010-11-05 22:33:53 +00006378 // Mark symbol as a thumb symbol.
6379 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
6380 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby146dcf22009-10-15 20:48:48 +00006381 return false;
6382}
6383
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006384/// parseDirectiveSyntax
Kevin Enderby146dcf22009-10-15 20:48:48 +00006385/// ::= .syntax unified | divided
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006386bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00006387 const AsmToken &Tok = Parser.getTok();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006388 if (Tok.isNot(AsmToken::Identifier))
6389 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer92d89982010-07-14 22:38:02 +00006390 StringRef Mode = Tok.getString();
Duncan Sands257eba42010-06-29 13:04:35 +00006391 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callanana83fd7d2010-01-19 20:27:46 +00006392 Parser.Lex();
Duncan Sands257eba42010-06-29 13:04:35 +00006393 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderbye9f2f0c2011-01-27 23:22:36 +00006394 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby146dcf22009-10-15 20:48:48 +00006395 else
6396 return Error(L, "unrecognized syntax mode in .syntax directive");
6397
6398 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan936b0d32010-01-19 21:44:56 +00006399 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00006400 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006401
6402 // TODO tell the MC streamer the mode
6403 // getParser().getStreamer().Emit???();
6404 return false;
6405}
6406
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006407/// parseDirectiveCode
Kevin Enderby146dcf22009-10-15 20:48:48 +00006408/// ::= .code 16 | 32
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006409bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00006410 const AsmToken &Tok = Parser.getTok();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006411 if (Tok.isNot(AsmToken::Integer))
6412 return Error(L, "unexpected token in .code directive");
Sean Callanan936b0d32010-01-19 21:44:56 +00006413 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands257eba42010-06-29 13:04:35 +00006414 if (Val == 16)
Sean Callanana83fd7d2010-01-19 20:27:46 +00006415 Parser.Lex();
Duncan Sands257eba42010-06-29 13:04:35 +00006416 else if (Val == 32)
Sean Callanana83fd7d2010-01-19 20:27:46 +00006417 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006418 else
6419 return Error(L, "invalid operand to .code directive");
6420
6421 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan936b0d32010-01-19 21:44:56 +00006422 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00006423 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006424
Evan Cheng284b4672011-07-08 22:36:29 +00006425 if (Val == 16) {
Jim Grosbachf471ac32011-09-06 18:46:23 +00006426 if (!isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00006427 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00006428 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng284b4672011-07-08 22:36:29 +00006429 } else {
Jim Grosbachf471ac32011-09-06 18:46:23 +00006430 if (isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00006431 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00006432 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Cheng45543ba2011-07-08 22:49:55 +00006433 }
Jim Grosbach2db0ea02010-11-05 22:40:53 +00006434
Kevin Enderby146dcf22009-10-15 20:48:48 +00006435 return false;
6436}
6437
Jim Grosbachab5830e2011-12-14 02:16:11 +00006438/// parseDirectiveReq
6439/// ::= name .req registername
6440bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
6441 Parser.Lex(); // Eat the '.req' token.
6442 unsigned Reg;
6443 SMLoc SRegLoc, ERegLoc;
6444 if (ParseRegister(Reg, SRegLoc, ERegLoc)) {
6445 Parser.EatToEndOfStatement();
6446 return Error(SRegLoc, "register name expected");
6447 }
6448
6449 // Shouldn't be anything else.
6450 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
6451 Parser.EatToEndOfStatement();
6452 return Error(Parser.getTok().getLoc(),
6453 "unexpected input in .req directive.");
6454 }
6455
6456 Parser.Lex(); // Consume the EndOfStatement
6457
6458 if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg)
6459 return Error(SRegLoc, "redefinition of '" + Name +
6460 "' does not match original.");
6461
6462 return false;
6463}
6464
6465/// parseDirectiveUneq
6466/// ::= .unreq registername
6467bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
6468 if (Parser.getTok().isNot(AsmToken::Identifier)) {
6469 Parser.EatToEndOfStatement();
6470 return Error(L, "unexpected input in .unreq directive.");
6471 }
6472 RegisterReqs.erase(Parser.getTok().getIdentifier());
6473 Parser.Lex(); // Eat the identifier.
6474 return false;
6475}
6476
Jason W Kim135d2442011-12-20 17:38:12 +00006477/// parseDirectiveArch
6478/// ::= .arch token
6479bool ARMAsmParser::parseDirectiveArch(SMLoc L) {
6480 return true;
6481}
6482
6483/// parseDirectiveEabiAttr
6484/// ::= .eabi_attribute int, int
6485bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
6486 return true;
6487}
6488
Sean Callanan643a5572010-04-07 20:29:34 +00006489extern "C" void LLVMInitializeARMAsmLexer();
6490
Kevin Enderby8be42bd2009-10-30 22:55:57 +00006491/// Force static initialization.
Kevin Enderbyccab3172009-09-15 00:27:25 +00006492extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng11424442011-07-26 00:24:13 +00006493 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
6494 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan643a5572010-04-07 20:29:34 +00006495 LLVMInitializeARMAsmLexer();
Kevin Enderbyccab3172009-09-15 00:27:25 +00006496}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00006497
Chris Lattner3e4582a2010-09-06 19:11:01 +00006498#define GET_REGISTER_MATCHER
6499#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00006500#include "ARMGenAsmMatcher.inc"