blob: 20b2e85aa91d5e0d469172638d62b216a14a9e3d [file] [log] [blame]
Kevin Enderbyca9c42c2009-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 Cheng94b95502011-07-26 00:24:13 +000010#include "MCTargetDesc/ARMBaseInfo.h"
Evan Chengee04a6d2011-07-20 23:34:39 +000011#include "MCTargetDesc/ARMAddressingModes.h"
12#include "MCTargetDesc/ARMMCExpr.h"
Chris Lattnerc6ef2772010-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 Espindola64695402011-05-16 16:17:21 +000016#include "llvm/MC/MCAsmInfo.h"
Jim Grosbach642fc9c2010-11-05 22:33:53 +000017#include "llvm/MC/MCContext.h"
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000018#include "llvm/MC/MCStreamer.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Evan Cheng78011362011-08-23 20:15:21 +000021#include "llvm/MC/MCInstrDesc.h"
Evan Cheng94b95502011-07-26 00:24:13 +000022#include "llvm/MC/MCRegisterInfo.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000023#include "llvm/MC/MCSubtargetInfo.h"
Evan Cheng94b95502011-07-26 00:24:13 +000024#include "llvm/MC/MCTargetAsmParser.h"
Jim Grosbach89df9962011-08-26 21:43:41 +000025#include "llvm/Support/MathExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000026#include "llvm/Support/SourceMgr.h"
Evan Cheng3e74d6f2011-08-24 18:08:43 +000027#include "llvm/Support/TargetRegistry.h"
Daniel Dunbarfa315de2010-08-11 06:37:12 +000028#include "llvm/Support/raw_ostream.h"
Jim Grosbach11e03e72011-08-22 18:50:36 +000029#include "llvm/ADT/BitVector.h"
Benjamin Kramer75ca4b92011-07-08 21:06:23 +000030#include "llvm/ADT/OwningPtr.h"
Evan Cheng94b95502011-07-26 00:24:13 +000031#include "llvm/ADT/STLExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000032#include "llvm/ADT/SmallVector.h"
Daniel Dunbar345a9a62010-08-11 06:37:20 +000033#include "llvm/ADT/StringSwitch.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000034#include "llvm/ADT/Twine.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000035
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000036using namespace llvm;
37
Chris Lattner3a697562010-10-28 17:20:03 +000038namespace {
Bill Wendling146018f2010-11-06 21:42:12 +000039
40class ARMOperand;
Jim Grosbach16c74252010-10-29 14:46:02 +000041
Jim Grosbach7636bf62011-12-02 00:35:16 +000042enum VectorLaneTy { NoLanes, AllLanes, IndexedLane };
Jim Grosbach98b05a52011-11-30 01:09:44 +000043
Evan Cheng94b95502011-07-26 00:24:13 +000044class ARMAsmParser : public MCTargetAsmParser {
Evan Chengffc0e732011-07-09 05:47:46 +000045 MCSubtargetInfo &STI;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000046 MCAsmParser &Parser;
47
Jim Grosbacha39cda72011-12-14 02:16:11 +000048 // Map of register aliases registers via the .req directive.
49 StringMap<unsigned> RegisterReqs;
50
Jim Grosbachf8e1e3e2011-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 Grosbacha1109882011-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 Grosbachf8e1e3e2011-08-29 22:24:09 +000079
80
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000081 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyca9c42c2009-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 Enderbyca9c42c2009-09-15 00:27:25 +000085 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
86
Jim Grosbach1355cf12011-07-26 17:10:22 +000087 int tryParseRegister();
88 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d87ec22011-07-26 20:41:24 +000089 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000090 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +000091 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000092 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
93 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbach7ce05792011-08-03 23:50:40 +000094 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
95 unsigned &ShiftAmount);
Jim Grosbach1355cf12011-07-26 17:10:22 +000096 bool parseDirectiveWord(unsigned Size, SMLoc L);
97 bool parseDirectiveThumb(SMLoc L);
Jim Grosbach9a70df92011-12-07 18:04:19 +000098 bool parseDirectiveARM(SMLoc L);
Jim Grosbach1355cf12011-07-26 17:10:22 +000099 bool parseDirectiveThumbFunc(SMLoc L);
100 bool parseDirectiveCode(SMLoc L);
101 bool parseDirectiveSyntax(SMLoc L);
Jim Grosbacha39cda72011-12-14 02:16:11 +0000102 bool parseDirectiveReq(StringRef Name, SMLoc L);
103 bool parseDirectiveUnreq(SMLoc L);
Jason W Kimd7c9e082011-12-20 17:38:12 +0000104 bool parseDirectiveArch(SMLoc L);
105 bool parseDirectiveEabiAttr(SMLoc L);
Kevin Enderby515d5092009-10-15 20:48:48 +0000106
Jim Grosbach1355cf12011-07-26 17:10:22 +0000107 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach89df9962011-08-26 21:43:41 +0000108 bool &CarrySetting, unsigned &ProcessorIMod,
109 StringRef &ITMask);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000110 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +0000111 bool &CanAcceptPredicationCode);
Jim Grosbach16c74252010-10-29 14:46:02 +0000112
Evan Chengebdeeab2011-07-08 01:53:10 +0000113 bool isThumb() const {
114 // FIXME: Can tablegen auto-generate this?
Evan Chengffc0e732011-07-09 05:47:46 +0000115 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000116 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000117 bool isThumbOne() const {
Evan Chengffc0e732011-07-09 05:47:46 +0000118 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000119 }
Jim Grosbach47a0d522011-08-16 20:45:50 +0000120 bool isThumbTwo() const {
121 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
122 }
Jim Grosbach194bd892011-08-16 22:20:01 +0000123 bool hasV6Ops() const {
124 return STI.getFeatureBits() & ARM::HasV6Ops;
125 }
James Molloyacad68d2011-09-28 14:21:38 +0000126 bool hasV7Ops() const {
127 return STI.getFeatureBits() & ARM::HasV7Ops;
128 }
Evan Cheng32869202011-07-08 22:36:29 +0000129 void SwitchMode() {
Evan Chengffc0e732011-07-09 05:47:46 +0000130 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
131 setAvailableFeatures(FB);
Evan Cheng32869202011-07-08 22:36:29 +0000132 }
James Molloyacad68d2011-09-28 14:21:38 +0000133 bool isMClass() const {
134 return STI.getFeatureBits() & ARM::FeatureMClass;
135 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000136
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000137 /// @name Auto-generated Match Functions
138 /// {
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000139
Chris Lattner0692ee62010-09-06 19:11:01 +0000140#define GET_ASSEMBLER_HEADER
141#include "ARMGenAsmMatcher.inc"
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000142
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000143 /// }
144
Jim Grosbach89df9962011-08-26 21:43:41 +0000145 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000146 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000147 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000148 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000149 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000150 OperandMatchResultTy parseCoprocOptionOperand(
151 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000152 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000153 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000154 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000155 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000156 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000157 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachf6c05252011-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 Grosbachc27d4f92011-07-22 17:44:50 +0000166 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach580f4a92011-07-25 22:20:28 +0000167 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000168 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000169 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000170 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach251bf252011-08-10 21:56:18 +0000171 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9d390362011-10-03 23:38:36 +0000172 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach862019c2011-10-18 23:02:30 +0000173 OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7636bf62011-12-02 00:35:16 +0000174 OperandMatchResultTy parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000175
176 // Asm Match Converter Methods
Jim Grosbacha77295d2011-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 Grosbacheeec0252011-09-08 00:39:19 +0000181 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
182 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachee2c2a42011-09-16 21:55:56 +0000183 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
184 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000185 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000186 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson9ab0f252011-08-26 20:43:14 +0000187 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
188 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach548340c2011-08-11 19:22:40 +0000189 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
190 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000191 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000192 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7b8f46c2011-08-11 21:17:22 +0000193 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
194 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-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 Grosbach2fd2b872011-08-10 20:29:19 +0000203 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
204 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach14605d12011-08-11 20:28:23 +0000205 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
206 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach623a4542011-08-10 22:42:16 +0000207 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
208 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach88ae2bc2011-08-19 22:07:46 +0000209 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
210 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach12431322011-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 Grosbach4334e032011-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 Grosbach189610f2011-07-26 18:25:39 +0000219
220 bool validateInstruction(MCInst &Inst,
221 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach83ec8772011-11-10 23:42:14 +0000222 bool processInstruction(MCInst &Inst,
Jim Grosbachf8fce712011-08-11 17:35:48 +0000223 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachd54b4e62011-08-16 21:12:37 +0000224 bool shouldOmitCCOutOperand(StringRef Mnemonic,
225 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach189610f2011-07-26 18:25:39 +0000226
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000227public:
Jim Grosbach47a0d522011-08-16 20:45:50 +0000228 enum ARMMatchResultTy {
Jim Grosbach194bd892011-08-16 22:20:01 +0000229 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000230 Match_RequiresNotITBlock,
Jim Grosbach194bd892011-08-16 22:20:01 +0000231 Match_RequiresV6,
232 Match_RequiresThumb2
Jim Grosbach47a0d522011-08-16 20:45:50 +0000233 };
234
Evan Chengffc0e732011-07-09 05:47:46 +0000235 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng94b95502011-07-26 00:24:13 +0000236 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Chengebdeeab2011-07-08 01:53:10 +0000237 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng32869202011-07-08 22:36:29 +0000238
Evan Chengebdeeab2011-07-08 01:53:10 +0000239 // Initialize the set of available features.
Evan Chengffc0e732011-07-09 05:47:46 +0000240 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000241
242 // Not in an ITBlock to start with.
243 ITState.CurPosition = ~0U;
Evan Chengebdeeab2011-07-08 01:53:10 +0000244 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000245
Jim Grosbach1355cf12011-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 Grosbach189610f2011-07-26 18:25:39 +0000249 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000250 bool ParseDirective(AsmToken DirectiveID);
251
Jim Grosbach47a0d522011-08-16 20:45:50 +0000252 unsigned checkTargetMatchPredicate(MCInst &Inst);
253
Jim Grosbach1355cf12011-07-26 17:10:22 +0000254 bool MatchAndEmitInstruction(SMLoc IDLoc,
255 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
256 MCStreamer &Out);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000257};
Jim Grosbach16c74252010-10-29 14:46:02 +0000258} // end anonymous namespace
259
Chris Lattner3a697562010-10-28 17:20:03 +0000260namespace {
261
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000262/// ARMOperand - Instances of this class represent a parsed ARM machine
263/// instruction.
Bill Wendling146018f2010-11-06 21:42:12 +0000264class ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000265 enum KindTy {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000266 k_CondCode,
267 k_CCOut,
268 k_ITCondMask,
269 k_CoprocNum,
270 k_CoprocReg,
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000271 k_CoprocOption,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000272 k_Immediate,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000273 k_MemBarrierOpt,
274 k_Memory,
275 k_PostIndexRegister,
276 k_MSRMask,
277 k_ProcIFlags,
Jim Grosbach460a9052011-10-07 23:56:00 +0000278 k_VectorIndex,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000279 k_Register,
280 k_RegisterList,
281 k_DPRRegisterList,
282 k_SPRRegisterList,
Jim Grosbach862019c2011-10-18 23:02:30 +0000283 k_VectorList,
Jim Grosbach98b05a52011-11-30 01:09:44 +0000284 k_VectorListAllLanes,
Jim Grosbach7636bf62011-12-02 00:35:16 +0000285 k_VectorListIndexed,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000286 k_ShiftedRegister,
287 k_ShiftedImmediate,
288 k_ShifterImmediate,
289 k_RotateImmediate,
290 k_BitfieldDescriptor,
291 k_Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000292 } Kind;
293
Sean Callanan76264762010-04-02 22:27:05 +0000294 SMLoc StartLoc, EndLoc;
Bill Wendling24d22d22010-11-18 21:50:54 +0000295 SmallVector<unsigned, 8> Registers;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000296
297 union {
298 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000299 ARMCC::CondCodes Val;
300 } CC;
301
302 struct {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000303 unsigned Val;
304 } Cop;
305
306 struct {
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000307 unsigned Val;
308 } CoprocOption;
309
310 struct {
Jim Grosbach89df9962011-08-26 21:43:41 +0000311 unsigned Mask:4;
312 } ITMask;
313
314 struct {
315 ARM_MB::MemBOpt Val;
316 } MBOpt;
317
318 struct {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000319 ARM_PROC::IFlags Val;
320 } IFlags;
321
322 struct {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000323 unsigned Val;
324 } MMask;
325
326 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000327 const char *Data;
328 unsigned Length;
329 } Tok;
330
331 struct {
332 unsigned RegNum;
333 } Reg;
334
Jim Grosbach862019c2011-10-18 23:02:30 +0000335 // A vector register list is a sequential list of 1 to 4 registers.
336 struct {
337 unsigned RegNum;
338 unsigned Count;
Jim Grosbach7636bf62011-12-02 00:35:16 +0000339 unsigned LaneIndex;
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +0000340 bool isDoubleSpaced;
Jim Grosbach862019c2011-10-18 23:02:30 +0000341 } VectorList;
342
Bill Wendling8155e5b2010-11-06 22:19:43 +0000343 struct {
Jim Grosbach460a9052011-10-07 23:56:00 +0000344 unsigned Val;
345 } VectorIndex;
346
347 struct {
Kevin Enderbycfe07242009-10-13 22:19:02 +0000348 const MCExpr *Val;
349 } Imm;
Jim Grosbach16c74252010-10-29 14:46:02 +0000350
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +0000351 /// Combined record for all forms of ARM address expressions.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000352 struct {
353 unsigned BaseRegNum;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000354 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
355 // was specified.
356 const MCConstantExpr *OffsetImm; // Offset immediate value
357 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
358 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbach57dcb852011-10-11 17:29:55 +0000359 unsigned ShiftImm; // shift for OffsetReg.
360 unsigned Alignment; // 0 = no alignment specified
Jim Grosbacheeaf1c12011-12-19 18:31:43 +0000361 // n = alignment in bytes (2, 4, 8, 16, or 32)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000362 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbache53c87b2011-10-11 15:59:20 +0000363 } Memory;
Owen Anderson00828302011-03-18 22:50:18 +0000364
365 struct {
Jim Grosbach7ce05792011-08-03 23:50:40 +0000366 unsigned RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000367 bool isAdd;
368 ARM_AM::ShiftOpc ShiftTy;
369 unsigned ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000370 } PostIdxReg;
371
372 struct {
Jim Grosbach580f4a92011-07-25 22:20:28 +0000373 bool isASR;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000374 unsigned Imm;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000375 } ShifterImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000376 struct {
377 ARM_AM::ShiftOpc ShiftTy;
378 unsigned SrcReg;
379 unsigned ShiftReg;
380 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000381 } RegShiftedReg;
Owen Anderson92a20222011-07-21 18:54:16 +0000382 struct {
383 ARM_AM::ShiftOpc ShiftTy;
384 unsigned SrcReg;
385 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000386 } RegShiftedImm;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000387 struct {
388 unsigned Imm;
389 } RotImm;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000390 struct {
391 unsigned LSB;
392 unsigned Width;
393 } Bitfield;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000394 };
Jim Grosbach16c74252010-10-29 14:46:02 +0000395
Bill Wendling146018f2010-11-06 21:42:12 +0000396 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
397public:
Sean Callanan76264762010-04-02 22:27:05 +0000398 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
399 Kind = o.Kind;
400 StartLoc = o.StartLoc;
401 EndLoc = o.EndLoc;
402 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000403 case k_CondCode:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000404 CC = o.CC;
405 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000406 case k_ITCondMask:
Jim Grosbach89df9962011-08-26 21:43:41 +0000407 ITMask = o.ITMask;
408 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000409 case k_Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000410 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000411 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000412 case k_CCOut:
413 case k_Register:
Sean Callanan76264762010-04-02 22:27:05 +0000414 Reg = o.Reg;
415 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000416 case k_RegisterList:
417 case k_DPRRegisterList:
418 case k_SPRRegisterList:
Bill Wendling24d22d22010-11-18 21:50:54 +0000419 Registers = o.Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000420 break;
Jim Grosbach862019c2011-10-18 23:02:30 +0000421 case k_VectorList:
Jim Grosbach98b05a52011-11-30 01:09:44 +0000422 case k_VectorListAllLanes:
Jim Grosbach7636bf62011-12-02 00:35:16 +0000423 case k_VectorListIndexed:
Jim Grosbach862019c2011-10-18 23:02:30 +0000424 VectorList = o.VectorList;
425 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000426 case k_CoprocNum:
427 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000428 Cop = o.Cop;
429 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000430 case k_CoprocOption:
431 CoprocOption = o.CoprocOption;
432 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000433 case k_Immediate:
Sean Callanan76264762010-04-02 22:27:05 +0000434 Imm = o.Imm;
435 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000436 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000437 MBOpt = o.MBOpt;
438 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000439 case k_Memory:
Jim Grosbache53c87b2011-10-11 15:59:20 +0000440 Memory = o.Memory;
Sean Callanan76264762010-04-02 22:27:05 +0000441 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000442 case k_PostIndexRegister:
Jim Grosbach7ce05792011-08-03 23:50:40 +0000443 PostIdxReg = o.PostIdxReg;
444 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000445 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000446 MMask = o.MMask;
447 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000448 case k_ProcIFlags:
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000449 IFlags = o.IFlags;
Owen Anderson00828302011-03-18 22:50:18 +0000450 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000451 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +0000452 ShifterImm = o.ShifterImm;
Owen Anderson00828302011-03-18 22:50:18 +0000453 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000454 case k_ShiftedRegister:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000455 RegShiftedReg = o.RegShiftedReg;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000456 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000457 case k_ShiftedImmediate:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000458 RegShiftedImm = o.RegShiftedImm;
Owen Anderson92a20222011-07-21 18:54:16 +0000459 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000460 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000461 RotImm = o.RotImm;
462 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000463 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000464 Bitfield = o.Bitfield;
465 break;
Jim Grosbach460a9052011-10-07 23:56:00 +0000466 case k_VectorIndex:
467 VectorIndex = o.VectorIndex;
468 break;
Sean Callanan76264762010-04-02 22:27:05 +0000469 }
470 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000471
Sean Callanan76264762010-04-02 22:27:05 +0000472 /// getStartLoc - Get the location of the first token of this operand.
473 SMLoc getStartLoc() const { return StartLoc; }
474 /// getEndLoc - Get the location of the last token of this operand.
475 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000476
Daniel Dunbar8462b302010-08-11 06:36:53 +0000477 ARMCC::CondCodes getCondCode() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000478 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000479 return CC.Val;
480 }
481
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000482 unsigned getCoproc() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000483 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000484 return Cop.Val;
485 }
486
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000487 StringRef getToken() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000488 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000489 return StringRef(Tok.Data, Tok.Length);
490 }
491
492 unsigned getReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000493 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling7729e062010-11-09 22:44:22 +0000494 return Reg.RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000495 }
496
Bill Wendling5fa22a12010-11-09 23:28:44 +0000497 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000498 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
499 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling24d22d22010-11-18 21:50:54 +0000500 return Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000501 }
502
Kevin Enderbycfe07242009-10-13 22:19:02 +0000503 const MCExpr *getImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000504 assert(isImm() && "Invalid access!");
Kevin Enderbycfe07242009-10-13 22:19:02 +0000505 return Imm.Val;
506 }
507
Jim Grosbach460a9052011-10-07 23:56:00 +0000508 unsigned getVectorIndex() const {
509 assert(Kind == k_VectorIndex && "Invalid access!");
510 return VectorIndex.Val;
511 }
512
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000513 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000514 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000515 return MBOpt.Val;
516 }
517
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000518 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000519 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000520 return IFlags.Val;
521 }
522
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000523 unsigned getMSRMask() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000524 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000525 return MMask.Val;
526 }
527
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000528 bool isCoprocNum() const { return Kind == k_CoprocNum; }
529 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000530 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000531 bool isCondCode() const { return Kind == k_CondCode; }
532 bool isCCOut() const { return Kind == k_CCOut; }
533 bool isITMask() const { return Kind == k_ITCondMask; }
534 bool isITCondCode() const { return Kind == k_CondCode; }
535 bool isImm() const { return Kind == k_Immediate; }
Jim Grosbach51222d12012-01-20 18:09:51 +0000536 bool isFPImm() const {
537 if (!isImm()) return false;
538 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
539 if (!CE) return false;
540 int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
541 return Val != -1;
542 }
Jim Grosbach4050bc42011-12-22 22:19:05 +0000543 bool isFBits16() const {
544 if (!isImm()) return false;
545 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
546 if (!CE) return false;
547 int64_t Value = CE->getValue();
548 return Value >= 0 && Value <= 16;
549 }
550 bool isFBits32() const {
551 if (!isImm()) return false;
552 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
553 if (!CE) return false;
554 int64_t Value = CE->getValue();
555 return Value >= 1 && Value <= 32;
556 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000557 bool isImm8s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000558 if (!isImm()) return false;
Jim Grosbacha77295d2011-09-08 22:07:06 +0000559 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
560 if (!CE) return false;
561 int64_t Value = CE->getValue();
562 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
563 }
Jim Grosbach72f39f82011-08-24 21:22:15 +0000564 bool isImm0_1020s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000565 if (!isImm()) return false;
Jim Grosbach72f39f82011-08-24 21:22:15 +0000566 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
567 if (!CE) return false;
568 int64_t Value = CE->getValue();
569 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
570 }
571 bool isImm0_508s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000572 if (!isImm()) return false;
Jim Grosbach72f39f82011-08-24 21:22:15 +0000573 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
574 if (!CE) return false;
575 int64_t Value = CE->getValue();
576 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
577 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000578 bool isImm0_255() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000579 if (!isImm()) return false;
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000580 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
581 if (!CE) return false;
582 int64_t Value = CE->getValue();
583 return Value >= 0 && Value < 256;
584 }
Jim Grosbach587f5062011-12-02 23:34:39 +0000585 bool isImm0_1() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000586 if (!isImm()) return false;
Jim Grosbach587f5062011-12-02 23:34:39 +0000587 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
588 if (!CE) return false;
589 int64_t Value = CE->getValue();
590 return Value >= 0 && Value < 2;
591 }
592 bool isImm0_3() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000593 if (!isImm()) return false;
Jim Grosbach587f5062011-12-02 23:34:39 +0000594 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
595 if (!CE) return false;
596 int64_t Value = CE->getValue();
597 return Value >= 0 && Value < 4;
598 }
Jim Grosbach83ab0702011-07-13 22:01:08 +0000599 bool isImm0_7() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000600 if (!isImm()) return false;
Jim Grosbach83ab0702011-07-13 22:01:08 +0000601 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
602 if (!CE) return false;
603 int64_t Value = CE->getValue();
604 return Value >= 0 && Value < 8;
605 }
606 bool isImm0_15() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000607 if (!isImm()) return false;
Jim Grosbach83ab0702011-07-13 22:01:08 +0000608 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
609 if (!CE) return false;
610 int64_t Value = CE->getValue();
611 return Value >= 0 && Value < 16;
612 }
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000613 bool isImm0_31() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000614 if (!isImm()) return false;
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000615 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
616 if (!CE) return false;
617 int64_t Value = CE->getValue();
618 return Value >= 0 && Value < 32;
619 }
Jim Grosbach730fe6c2011-12-08 01:30:04 +0000620 bool isImm0_63() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000621 if (!isImm()) return false;
Jim Grosbach730fe6c2011-12-08 01:30:04 +0000622 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
623 if (!CE) return false;
624 int64_t Value = CE->getValue();
625 return Value >= 0 && Value < 64;
626 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000627 bool isImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000628 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000629 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
630 if (!CE) return false;
631 int64_t Value = CE->getValue();
632 return Value == 8;
633 }
634 bool isImm16() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000635 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000636 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
637 if (!CE) return false;
638 int64_t Value = CE->getValue();
639 return Value == 16;
640 }
641 bool isImm32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000642 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000643 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
644 if (!CE) return false;
645 int64_t Value = CE->getValue();
646 return Value == 32;
647 }
Jim Grosbach6b044c22011-12-08 22:06:06 +0000648 bool isShrImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000649 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000650 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
651 if (!CE) return false;
652 int64_t Value = CE->getValue();
653 return Value > 0 && Value <= 8;
654 }
655 bool isShrImm16() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000656 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000657 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
658 if (!CE) return false;
659 int64_t Value = CE->getValue();
660 return Value > 0 && Value <= 16;
661 }
662 bool isShrImm32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000663 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000664 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
665 if (!CE) return false;
666 int64_t Value = CE->getValue();
667 return Value > 0 && Value <= 32;
668 }
669 bool isShrImm64() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000670 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000671 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
672 if (!CE) return false;
673 int64_t Value = CE->getValue();
674 return Value > 0 && Value <= 64;
675 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000676 bool isImm1_7() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000677 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000678 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
679 if (!CE) return false;
680 int64_t Value = CE->getValue();
681 return Value > 0 && Value < 8;
682 }
683 bool isImm1_15() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000684 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000685 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
686 if (!CE) return false;
687 int64_t Value = CE->getValue();
688 return Value > 0 && Value < 16;
689 }
690 bool isImm1_31() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000691 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000692 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
693 if (!CE) return false;
694 int64_t Value = CE->getValue();
695 return Value > 0 && Value < 32;
696 }
Jim Grosbachf4943352011-07-25 23:09:14 +0000697 bool isImm1_16() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000698 if (!isImm()) return false;
Jim Grosbachf4943352011-07-25 23:09:14 +0000699 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
700 if (!CE) return false;
701 int64_t Value = CE->getValue();
702 return Value > 0 && Value < 17;
703 }
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000704 bool isImm1_32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000705 if (!isImm()) return false;
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000706 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
707 if (!CE) return false;
708 int64_t Value = CE->getValue();
709 return Value > 0 && Value < 33;
710 }
Jim Grosbachee10ff82011-11-10 19:18:01 +0000711 bool isImm0_32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000712 if (!isImm()) return false;
Jim Grosbachee10ff82011-11-10 19:18:01 +0000713 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
714 if (!CE) return false;
715 int64_t Value = CE->getValue();
716 return Value >= 0 && Value < 33;
717 }
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000718 bool isImm0_65535() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000719 if (!isImm()) return false;
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000720 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
721 if (!CE) return false;
722 int64_t Value = CE->getValue();
723 return Value >= 0 && Value < 65536;
724 }
Jim Grosbachffa32252011-07-19 19:13:28 +0000725 bool isImm0_65535Expr() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000726 if (!isImm()) return false;
Jim Grosbachffa32252011-07-19 19:13:28 +0000727 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
728 // If it's not a constant expression, it'll generate a fixup and be
729 // handled later.
730 if (!CE) return true;
731 int64_t Value = CE->getValue();
732 return Value >= 0 && Value < 65536;
733 }
Jim Grosbached838482011-07-26 16:24:27 +0000734 bool isImm24bit() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000735 if (!isImm()) return false;
Jim Grosbached838482011-07-26 16:24:27 +0000736 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
737 if (!CE) return false;
738 int64_t Value = CE->getValue();
739 return Value >= 0 && Value <= 0xffffff;
740 }
Jim Grosbach70939ee2011-08-17 21:51:27 +0000741 bool isImmThumbSR() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000742 if (!isImm()) return false;
Jim Grosbach70939ee2011-08-17 21:51:27 +0000743 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
744 if (!CE) return false;
745 int64_t Value = CE->getValue();
746 return Value > 0 && Value < 33;
747 }
Jim Grosbachf6c05252011-07-21 17:23:04 +0000748 bool isPKHLSLImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000749 if (!isImm()) return false;
Jim Grosbachf6c05252011-07-21 17:23:04 +0000750 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
751 if (!CE) return false;
752 int64_t Value = CE->getValue();
753 return Value >= 0 && Value < 32;
754 }
755 bool isPKHASRImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000756 if (!isImm()) return false;
Jim Grosbachf6c05252011-07-21 17:23:04 +0000757 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
758 if (!CE) return false;
759 int64_t Value = CE->getValue();
760 return Value > 0 && Value <= 32;
761 }
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000762 bool isARMSOImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000763 if (!isImm()) return false;
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000764 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
765 if (!CE) return false;
766 int64_t Value = CE->getValue();
767 return ARM_AM::getSOImmVal(Value) != -1;
768 }
Jim Grosbache70ec842011-10-28 22:50:54 +0000769 bool isARMSOImmNot() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000770 if (!isImm()) return false;
Jim Grosbache70ec842011-10-28 22:50:54 +0000771 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
772 if (!CE) return false;
773 int64_t Value = CE->getValue();
774 return ARM_AM::getSOImmVal(~Value) != -1;
775 }
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000776 bool isARMSOImmNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000777 if (!isImm()) return false;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000778 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
779 if (!CE) return false;
780 int64_t Value = CE->getValue();
781 return ARM_AM::getSOImmVal(-Value) != -1;
782 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000783 bool isT2SOImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000784 if (!isImm()) return false;
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000785 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
786 if (!CE) return false;
787 int64_t Value = CE->getValue();
788 return ARM_AM::getT2SOImmVal(Value) != -1;
789 }
Jim Grosbach89a63372011-10-28 22:36:30 +0000790 bool isT2SOImmNot() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000791 if (!isImm()) return false;
Jim Grosbach89a63372011-10-28 22:36:30 +0000792 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
793 if (!CE) return false;
794 int64_t Value = CE->getValue();
795 return ARM_AM::getT2SOImmVal(~Value) != -1;
796 }
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000797 bool isT2SOImmNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000798 if (!isImm()) return false;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000799 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
800 if (!CE) return false;
801 int64_t Value = CE->getValue();
802 return ARM_AM::getT2SOImmVal(-Value) != -1;
803 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000804 bool isSetEndImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000805 if (!isImm()) return false;
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000806 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
807 if (!CE) return false;
808 int64_t Value = CE->getValue();
809 return Value == 1 || Value == 0;
810 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000811 bool isReg() const { return Kind == k_Register; }
812 bool isRegList() const { return Kind == k_RegisterList; }
813 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
814 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
815 bool isToken() const { return Kind == k_Token; }
816 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
817 bool isMemory() const { return Kind == k_Memory; }
818 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
819 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
820 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
821 bool isRotImm() const { return Kind == k_RotateImmediate; }
822 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
823 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000824 bool isPostIdxReg() const {
Jim Grosbach430052b2011-11-14 17:52:47 +0000825 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000826 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000827 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000828 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000829 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000830 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000831 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
832 (alignOK || Memory.Alignment == 0);
833 }
Jim Grosbach0b4c6732012-01-18 22:46:46 +0000834 bool isMemPCRelImm12() const {
835 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
836 return false;
837 // Base register must be PC.
838 if (Memory.BaseRegNum != ARM::PC)
839 return false;
840 // Immediate offset in range [-4095, 4095].
841 if (!Memory.OffsetImm) return true;
842 int64_t Val = Memory.OffsetImm->getValue();
843 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
844 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000845 bool isAlignedMemory() const {
846 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000847 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000848 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000849 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000850 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000851 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000852 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000853 if (!Memory.OffsetImm) return true;
854 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000855 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000856 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000857 bool isAM2OffsetImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000858 if (!isImm()) return false;
Jim Grosbach039c2e12011-08-04 23:01:30 +0000859 // Immediate offset in range [-4095, 4095].
860 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
861 if (!CE) return false;
862 int64_t Val = CE->getValue();
863 return Val > -4096 && Val < 4096;
864 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000865 bool isAddrMode3() const {
Jim Grosbach2f196742011-12-19 23:06:24 +0000866 // If we have an immediate that's not a constant, treat it as a label
867 // reference needing a fixup. If it is a constant, it's something else
868 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000869 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach2f196742011-12-19 23:06:24 +0000870 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000871 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000872 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000873 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000874 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000875 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000876 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000877 if (!Memory.OffsetImm) return true;
878 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000879 return Val > -256 && Val < 256;
880 }
881 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000882 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000883 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000884 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000885 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
886 // Immediate offset in range [-255, 255].
887 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
888 if (!CE) return false;
889 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000890 // Special case, #-0 is INT32_MIN.
891 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000892 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000893 bool isAddrMode5() const {
Jim Grosbach681460f2011-11-01 01:24:45 +0000894 // If we have an immediate that's not a constant, treat it as a label
895 // reference needing a fixup. If it is a constant, it's something else
896 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000897 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach681460f2011-11-01 01:24:45 +0000898 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000899 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000900 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000901 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000902 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000903 if (!Memory.OffsetImm) return true;
904 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000905 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbach681460f2011-11-01 01:24:45 +0000906 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000907 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000908 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000909 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000910 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000911 return false;
912 return true;
913 }
914 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000915 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000916 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
917 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000918 return false;
919 return true;
920 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000921 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000922 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000923 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000924 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000925 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000926 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000927 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
928 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000929 return false;
930 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000931 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000932 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000933 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000934 return false;
935 return true;
936 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000937 bool isMemThumbRR() const {
938 // Thumb reg+reg addressing is simple. Just two registers, a base and
939 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000940 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000941 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000942 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000943 return isARMLowRegister(Memory.BaseRegNum) &&
944 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000945 }
946 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000947 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000948 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000949 return false;
950 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000951 if (!Memory.OffsetImm) return true;
952 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000953 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
954 }
Jim Grosbach38466302011-08-19 18:55:51 +0000955 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000956 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000957 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000958 return false;
959 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000960 if (!Memory.OffsetImm) return true;
961 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +0000962 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
963 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000964 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000965 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000966 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000967 return false;
968 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000969 if (!Memory.OffsetImm) return true;
970 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000971 return Val >= 0 && Val <= 31;
972 }
Jim Grosbachecd85892011-08-19 18:13:48 +0000973 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000974 if (!isMemory() || Memory.OffsetRegNum != 0 ||
975 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +0000976 return false;
977 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000978 if (!Memory.OffsetImm) return true;
979 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000980 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000981 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000982 bool isMemImm8s4Offset() const {
Jim Grosbach2f196742011-12-19 23:06:24 +0000983 // If we have an immediate that's not a constant, treat it as a label
984 // reference needing a fixup. If it is a constant, it's something else
985 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000986 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach2f196742011-12-19 23:06:24 +0000987 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000988 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000989 return false;
990 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000991 if (!Memory.OffsetImm) return true;
992 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +0000993 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
994 }
Jim Grosbachb6aed502011-09-09 18:37:27 +0000995 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000996 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +0000997 return false;
998 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000999 if (!Memory.OffsetImm) return true;
1000 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +00001001 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
1002 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001003 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001004 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001005 return false;
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001006 // Base reg of PC isn't allowed for these encodings.
1007 if (Memory.BaseRegNum == ARM::PC) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001008 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001009 if (!Memory.OffsetImm) return true;
1010 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +00001011 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001012 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001013 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001014 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001015 return false;
1016 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001017 if (!Memory.OffsetImm) return true;
1018 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001019 return Val >= 0 && Val < 256;
1020 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001021 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001022 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001023 return false;
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001024 // Base reg of PC isn't allowed for these encodings.
1025 if (Memory.BaseRegNum == ARM::PC) return false;
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001026 // Immediate offset in range [-255, -1].
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001027 if (!Memory.OffsetImm) return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001028 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001029 return (Val == INT32_MIN) || (Val > -256 && Val < 0);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001030 }
1031 bool isMemUImm12Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001032 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001033 return false;
1034 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001035 if (!Memory.OffsetImm) return true;
1036 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001037 return (Val >= 0 && Val < 4096);
1038 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001039 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +00001040 // If we have an immediate that's not a constant, treat it as a label
1041 // reference needing a fixup. If it is a constant, it's something else
1042 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001043 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +00001044 return true;
1045
Jim Grosbach57dcb852011-10-11 17:29:55 +00001046 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001047 return false;
1048 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001049 if (!Memory.OffsetImm) return true;
1050 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +00001051 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001052 }
1053 bool isPostIdxImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001054 if (!isImm()) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001055 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1056 if (!CE) return false;
1057 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +00001058 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001059 }
Jim Grosbach2bd01182011-10-11 21:55:36 +00001060 bool isPostIdxImm8s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001061 if (!isImm()) return false;
Jim Grosbach2bd01182011-10-11 21:55:36 +00001062 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1063 if (!CE) return false;
1064 int64_t Val = CE->getValue();
1065 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1066 (Val == INT32_MIN);
1067 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001068
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001069 bool isMSRMask() const { return Kind == k_MSRMask; }
1070 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001071
Jim Grosbach0e387b22011-10-17 22:26:03 +00001072 // NEON operands.
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001073 bool isSingleSpacedVectorList() const {
1074 return Kind == k_VectorList && !VectorList.isDoubleSpaced;
1075 }
1076 bool isDoubleSpacedVectorList() const {
1077 return Kind == k_VectorList && VectorList.isDoubleSpaced;
1078 }
Jim Grosbach862019c2011-10-18 23:02:30 +00001079 bool isVecListOneD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001080 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach862019c2011-10-18 23:02:30 +00001081 return VectorList.Count == 1;
1082 }
1083
Jim Grosbach280dfad2011-10-21 18:54:25 +00001084 bool isVecListTwoD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001085 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach280dfad2011-10-21 18:54:25 +00001086 return VectorList.Count == 2;
1087 }
1088
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001089 bool isVecListThreeD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001090 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001091 return VectorList.Count == 3;
1092 }
1093
Jim Grosbachb6310312011-10-21 20:35:01 +00001094 bool isVecListFourD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001095 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachb6310312011-10-21 20:35:01 +00001096 return VectorList.Count == 4;
1097 }
1098
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001099 bool isVecListTwoQ() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001100 if (!isDoubleSpacedVectorList()) return false;
1101 return VectorList.Count == 2;
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001102 }
1103
Jim Grosbachc387fc62012-01-23 23:20:46 +00001104 bool isVecListThreeQ() const {
1105 if (!isDoubleSpacedVectorList()) return false;
1106 return VectorList.Count == 3;
1107 }
1108
Jim Grosbach7945ead2012-01-24 00:43:12 +00001109 bool isVecListFourQ() const {
1110 if (!isDoubleSpacedVectorList()) return false;
1111 return VectorList.Count == 4;
1112 }
1113
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001114 bool isSingleSpacedVectorAllLanes() const {
1115 return Kind == k_VectorListAllLanes && !VectorList.isDoubleSpaced;
1116 }
1117 bool isDoubleSpacedVectorAllLanes() const {
1118 return Kind == k_VectorListAllLanes && VectorList.isDoubleSpaced;
1119 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00001120 bool isVecListOneDAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001121 if (!isSingleSpacedVectorAllLanes()) return false;
Jim Grosbach98b05a52011-11-30 01:09:44 +00001122 return VectorList.Count == 1;
1123 }
1124
Jim Grosbach13af2222011-11-30 18:21:25 +00001125 bool isVecListTwoDAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001126 if (!isSingleSpacedVectorAllLanes()) return false;
1127 return VectorList.Count == 2;
1128 }
1129
1130 bool isVecListTwoQAllLanes() const {
1131 if (!isDoubleSpacedVectorAllLanes()) return false;
Jim Grosbach13af2222011-11-30 18:21:25 +00001132 return VectorList.Count == 2;
1133 }
1134
Jim Grosbach5e59f7e2012-01-24 23:47:04 +00001135 bool isVecListThreeDAllLanes() const {
1136 if (!isSingleSpacedVectorAllLanes()) return false;
1137 return VectorList.Count == 3;
1138 }
1139
1140 bool isVecListThreeQAllLanes() const {
1141 if (!isDoubleSpacedVectorAllLanes()) return false;
1142 return VectorList.Count == 3;
1143 }
1144
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001145 bool isSingleSpacedVectorIndexed() const {
1146 return Kind == k_VectorListIndexed && !VectorList.isDoubleSpaced;
1147 }
1148 bool isDoubleSpacedVectorIndexed() const {
1149 return Kind == k_VectorListIndexed && VectorList.isDoubleSpaced;
1150 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00001151 bool isVecListOneDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001152 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach7636bf62011-12-02 00:35:16 +00001153 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1154 }
1155
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001156 bool isVecListOneDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001157 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001158 return VectorList.Count == 1 && VectorList.LaneIndex <= 3;
1159 }
1160
1161 bool isVecListOneDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001162 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001163 return VectorList.Count == 1 && VectorList.LaneIndex <= 1;
1164 }
1165
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001166 bool isVecListTwoDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001167 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001168 return VectorList.Count == 2 && VectorList.LaneIndex <= 7;
1169 }
1170
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001171 bool isVecListTwoDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001172 if (!isSingleSpacedVectorIndexed()) return false;
1173 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1174 }
1175
1176 bool isVecListTwoQWordIndexed() const {
1177 if (!isDoubleSpacedVectorIndexed()) return false;
1178 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1179 }
1180
1181 bool isVecListTwoQHWordIndexed() const {
1182 if (!isDoubleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001183 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1184 }
1185
1186 bool isVecListTwoDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001187 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001188 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1189 }
1190
Jim Grosbach3a678af2012-01-23 21:53:26 +00001191 bool isVecListThreeDByteIndexed() const {
1192 if (!isSingleSpacedVectorIndexed()) return false;
1193 return VectorList.Count == 3 && VectorList.LaneIndex <= 7;
1194 }
1195
1196 bool isVecListThreeDHWordIndexed() const {
1197 if (!isSingleSpacedVectorIndexed()) return false;
1198 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1199 }
1200
1201 bool isVecListThreeQWordIndexed() const {
1202 if (!isDoubleSpacedVectorIndexed()) return false;
1203 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1204 }
1205
1206 bool isVecListThreeQHWordIndexed() const {
1207 if (!isDoubleSpacedVectorIndexed()) return false;
1208 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1209 }
1210
1211 bool isVecListThreeDWordIndexed() const {
1212 if (!isSingleSpacedVectorIndexed()) return false;
1213 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1214 }
1215
Jim Grosbache983a132012-01-24 18:37:25 +00001216 bool isVecListFourDByteIndexed() const {
1217 if (!isSingleSpacedVectorIndexed()) return false;
1218 return VectorList.Count == 4 && VectorList.LaneIndex <= 7;
1219 }
1220
1221 bool isVecListFourDHWordIndexed() const {
1222 if (!isSingleSpacedVectorIndexed()) return false;
1223 return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1224 }
1225
1226 bool isVecListFourQWordIndexed() const {
1227 if (!isDoubleSpacedVectorIndexed()) return false;
1228 return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1229 }
1230
1231 bool isVecListFourQHWordIndexed() const {
1232 if (!isDoubleSpacedVectorIndexed()) return false;
1233 return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1234 }
1235
1236 bool isVecListFourDWordIndexed() const {
1237 if (!isSingleSpacedVectorIndexed()) return false;
1238 return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1239 }
1240
Jim Grosbach460a9052011-10-07 23:56:00 +00001241 bool isVectorIndex8() const {
1242 if (Kind != k_VectorIndex) return false;
1243 return VectorIndex.Val < 8;
1244 }
1245 bool isVectorIndex16() const {
1246 if (Kind != k_VectorIndex) return false;
1247 return VectorIndex.Val < 4;
1248 }
1249 bool isVectorIndex32() const {
1250 if (Kind != k_VectorIndex) return false;
1251 return VectorIndex.Val < 2;
1252 }
1253
Jim Grosbach0e387b22011-10-17 22:26:03 +00001254 bool isNEONi8splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001255 if (!isImm()) return false;
Jim Grosbach0e387b22011-10-17 22:26:03 +00001256 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1257 // Must be a constant.
1258 if (!CE) return false;
1259 int64_t Value = CE->getValue();
1260 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1261 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +00001262 return Value >= 0 && Value < 256;
1263 }
Jim Grosbach460a9052011-10-07 23:56:00 +00001264
Jim Grosbachea461102011-10-17 23:09:09 +00001265 bool isNEONi16splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001266 if (!isImm()) return false;
Jim Grosbachea461102011-10-17 23:09:09 +00001267 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1268 // Must be a constant.
1269 if (!CE) return false;
1270 int64_t Value = CE->getValue();
1271 // i16 value in the range [0,255] or [0x0100, 0xff00]
1272 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1273 }
1274
Jim Grosbach6248a542011-10-18 00:22:00 +00001275 bool isNEONi32splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001276 if (!isImm()) return false;
Jim Grosbach6248a542011-10-18 00:22:00 +00001277 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1278 // Must be a constant.
1279 if (!CE) return false;
1280 int64_t Value = CE->getValue();
1281 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1282 return (Value >= 0 && Value < 256) ||
1283 (Value >= 0x0100 && Value <= 0xff00) ||
1284 (Value >= 0x010000 && Value <= 0xff0000) ||
1285 (Value >= 0x01000000 && Value <= 0xff000000);
1286 }
1287
1288 bool isNEONi32vmov() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001289 if (!isImm()) return false;
Jim Grosbach6248a542011-10-18 00:22:00 +00001290 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1291 // Must be a constant.
1292 if (!CE) return false;
1293 int64_t Value = CE->getValue();
1294 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1295 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1296 return (Value >= 0 && Value < 256) ||
1297 (Value >= 0x0100 && Value <= 0xff00) ||
1298 (Value >= 0x010000 && Value <= 0xff0000) ||
1299 (Value >= 0x01000000 && Value <= 0xff000000) ||
1300 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1301 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1302 }
Jim Grosbach9b087852011-12-19 23:51:07 +00001303 bool isNEONi32vmovNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001304 if (!isImm()) return false;
Jim Grosbach9b087852011-12-19 23:51:07 +00001305 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1306 // Must be a constant.
1307 if (!CE) return false;
1308 int64_t Value = ~CE->getValue();
1309 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1310 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1311 return (Value >= 0 && Value < 256) ||
1312 (Value >= 0x0100 && Value <= 0xff00) ||
1313 (Value >= 0x010000 && Value <= 0xff0000) ||
1314 (Value >= 0x01000000 && Value <= 0xff000000) ||
1315 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1316 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1317 }
Jim Grosbach6248a542011-10-18 00:22:00 +00001318
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001319 bool isNEONi64splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001320 if (!isImm()) return false;
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001321 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1322 // Must be a constant.
1323 if (!CE) return false;
1324 uint64_t Value = CE->getValue();
1325 // i64 value with each byte being either 0 or 0xff.
1326 for (unsigned i = 0; i < 8; ++i)
1327 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1328 return true;
1329 }
1330
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001331 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001332 // Add as immediates when possible. Null MCExpr = 0.
1333 if (Expr == 0)
1334 Inst.addOperand(MCOperand::CreateImm(0));
1335 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001336 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1337 else
1338 Inst.addOperand(MCOperand::CreateExpr(Expr));
1339 }
1340
Daniel Dunbar8462b302010-08-11 06:36:53 +00001341 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001342 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001343 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001344 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1345 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001346 }
1347
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001348 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1349 assert(N == 1 && "Invalid number of operands!");
1350 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1351 }
1352
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001353 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1354 assert(N == 1 && "Invalid number of operands!");
1355 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1356 }
1357
1358 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1359 assert(N == 1 && "Invalid number of operands!");
1360 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1361 }
1362
Jim Grosbach89df9962011-08-26 21:43:41 +00001363 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1364 assert(N == 1 && "Invalid number of operands!");
1365 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1366 }
1367
1368 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1369 assert(N == 1 && "Invalid number of operands!");
1370 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1371 }
1372
Jim Grosbachd67641b2010-12-06 18:21:12 +00001373 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1374 assert(N == 1 && "Invalid number of operands!");
1375 Inst.addOperand(MCOperand::CreateReg(getReg()));
1376 }
1377
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001378 void addRegOperands(MCInst &Inst, unsigned N) const {
1379 assert(N == 1 && "Invalid number of operands!");
1380 Inst.addOperand(MCOperand::CreateReg(getReg()));
1381 }
1382
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001383 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001384 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001385 assert(isRegShiftedReg() &&
1386 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001387 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1388 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001389 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001390 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001391 }
1392
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001393 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001394 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001395 assert(isRegShiftedImm() &&
1396 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001397 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001398 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001399 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001400 }
1401
Jim Grosbach580f4a92011-07-25 22:20:28 +00001402 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001403 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001404 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1405 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001406 }
1407
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001408 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001409 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001410 const SmallVectorImpl<unsigned> &RegList = getRegList();
1411 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001412 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1413 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001414 }
1415
Bill Wendling0f630752010-11-17 04:32:08 +00001416 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1417 addRegListOperands(Inst, N);
1418 }
1419
1420 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1421 addRegListOperands(Inst, N);
1422 }
1423
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001424 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1425 assert(N == 1 && "Invalid number of operands!");
1426 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1427 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1428 }
1429
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001430 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1431 assert(N == 1 && "Invalid number of operands!");
1432 // Munge the lsb/width into a bitfield mask.
1433 unsigned lsb = Bitfield.LSB;
1434 unsigned width = Bitfield.Width;
1435 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1436 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1437 (32 - (lsb + width)));
1438 Inst.addOperand(MCOperand::CreateImm(Mask));
1439 }
1440
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001441 void addImmOperands(MCInst &Inst, unsigned N) const {
1442 assert(N == 1 && "Invalid number of operands!");
1443 addExpr(Inst, getImm());
1444 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001445
Jim Grosbach4050bc42011-12-22 22:19:05 +00001446 void addFBits16Operands(MCInst &Inst, unsigned N) const {
1447 assert(N == 1 && "Invalid number of operands!");
1448 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1449 Inst.addOperand(MCOperand::CreateImm(16 - CE->getValue()));
1450 }
1451
1452 void addFBits32Operands(MCInst &Inst, unsigned N) const {
1453 assert(N == 1 && "Invalid number of operands!");
1454 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1455 Inst.addOperand(MCOperand::CreateImm(32 - CE->getValue()));
1456 }
1457
Jim Grosbach9d390362011-10-03 23:38:36 +00001458 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1459 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach51222d12012-01-20 18:09:51 +00001460 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1461 int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
1462 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach9d390362011-10-03 23:38:36 +00001463 }
1464
Jim Grosbacha77295d2011-09-08 22:07:06 +00001465 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1466 assert(N == 1 && "Invalid number of operands!");
1467 // FIXME: We really want to scale the value here, but the LDRD/STRD
1468 // instruction don't encode operands that way yet.
1469 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1470 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1471 }
1472
Jim Grosbach72f39f82011-08-24 21:22:15 +00001473 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1474 assert(N == 1 && "Invalid number of operands!");
1475 // The immediate is scaled by four in the encoding and is stored
1476 // in the MCInst as such. Lop off the low two bits here.
1477 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1478 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1479 }
1480
1481 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1482 assert(N == 1 && "Invalid number of operands!");
1483 // The immediate is scaled by four in the encoding and is stored
1484 // in the MCInst as such. Lop off the low two bits here.
1485 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1486 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1487 }
1488
Jim Grosbachf4943352011-07-25 23:09:14 +00001489 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1490 assert(N == 1 && "Invalid number of operands!");
1491 // The constant encodes as the immediate-1, and we store in the instruction
1492 // the bits as encoded, so subtract off one here.
1493 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1494 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1495 }
1496
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001497 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1498 assert(N == 1 && "Invalid number of operands!");
1499 // The constant encodes as the immediate-1, and we store in the instruction
1500 // the bits as encoded, so subtract off one here.
1501 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1502 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1503 }
1504
Jim Grosbach70939ee2011-08-17 21:51:27 +00001505 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1506 assert(N == 1 && "Invalid number of operands!");
1507 // The constant encodes as the immediate, except for 32, which encodes as
1508 // zero.
1509 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1510 unsigned Imm = CE->getValue();
1511 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1512 }
1513
Jim Grosbachf6c05252011-07-21 17:23:04 +00001514 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1515 assert(N == 1 && "Invalid number of operands!");
1516 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1517 // the instruction as well.
1518 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1519 int Val = CE->getValue();
1520 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1521 }
1522
Jim Grosbach89a63372011-10-28 22:36:30 +00001523 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1524 assert(N == 1 && "Invalid number of operands!");
1525 // The operand is actually a t2_so_imm, but we have its bitwise
1526 // negation in the assembly source, so twiddle it here.
1527 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1528 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1529 }
1530
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001531 void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1532 assert(N == 1 && "Invalid number of operands!");
1533 // The operand is actually a t2_so_imm, but we have its
1534 // negation in the assembly source, so twiddle it here.
1535 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1536 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1537 }
1538
Jim Grosbache70ec842011-10-28 22:50:54 +00001539 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1540 assert(N == 1 && "Invalid number of operands!");
1541 // The operand is actually a so_imm, but we have its bitwise
1542 // negation in the assembly source, so twiddle it here.
1543 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1544 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1545 }
1546
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001547 void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
1548 assert(N == 1 && "Invalid number of operands!");
1549 // The operand is actually a so_imm, but we have its
1550 // negation in the assembly source, so twiddle it here.
1551 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1552 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1553 }
1554
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001555 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1556 assert(N == 1 && "Invalid number of operands!");
1557 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1558 }
1559
Jim Grosbach7ce05792011-08-03 23:50:40 +00001560 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1561 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001562 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001563 }
1564
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001565 void addMemPCRelImm12Operands(MCInst &Inst, unsigned N) const {
1566 assert(N == 1 && "Invalid number of operands!");
1567 int32_t Imm = Memory.OffsetImm->getValue();
1568 // FIXME: Handle #-0
1569 if (Imm == INT32_MIN) Imm = 0;
1570 Inst.addOperand(MCOperand::CreateImm(Imm));
1571 }
1572
Jim Grosbach57dcb852011-10-11 17:29:55 +00001573 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1574 assert(N == 2 && "Invalid number of operands!");
1575 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1576 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1577 }
1578
Jim Grosbach7ce05792011-08-03 23:50:40 +00001579 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1580 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001581 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1582 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001583 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1584 // Special case for #-0
1585 if (Val == INT32_MIN) Val = 0;
1586 if (Val < 0) Val = -Val;
1587 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1588 } else {
1589 // For register offset, we encode the shift type and negation flag
1590 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001591 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1592 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001593 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001594 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1595 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001596 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001597 }
1598
Jim Grosbach039c2e12011-08-04 23:01:30 +00001599 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1600 assert(N == 2 && "Invalid number of operands!");
1601 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1602 assert(CE && "non-constant AM2OffsetImm operand!");
1603 int32_t Val = CE->getValue();
1604 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1605 // Special case for #-0
1606 if (Val == INT32_MIN) Val = 0;
1607 if (Val < 0) Val = -Val;
1608 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1609 Inst.addOperand(MCOperand::CreateReg(0));
1610 Inst.addOperand(MCOperand::CreateImm(Val));
1611 }
1612
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001613 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1614 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001615 // If we have an immediate that's not a constant, treat it as a label
1616 // reference needing a fixup. If it is a constant, it's something else
1617 // and we reject it.
1618 if (isImm()) {
1619 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1620 Inst.addOperand(MCOperand::CreateReg(0));
1621 Inst.addOperand(MCOperand::CreateImm(0));
1622 return;
1623 }
1624
Jim Grosbache53c87b2011-10-11 15:59:20 +00001625 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1626 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001627 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1628 // Special case for #-0
1629 if (Val == INT32_MIN) Val = 0;
1630 if (Val < 0) Val = -Val;
1631 Val = ARM_AM::getAM3Opc(AddSub, Val);
1632 } else {
1633 // For register offset, we encode the shift type and negation flag
1634 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001635 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001636 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001637 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1638 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001639 Inst.addOperand(MCOperand::CreateImm(Val));
1640 }
1641
1642 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1643 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001644 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001645 int32_t Val =
1646 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1647 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1648 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001649 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001650 }
1651
1652 // Constant offset.
1653 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1654 int32_t Val = CE->getValue();
1655 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1656 // Special case for #-0
1657 if (Val == INT32_MIN) Val = 0;
1658 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001659 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001660 Inst.addOperand(MCOperand::CreateReg(0));
1661 Inst.addOperand(MCOperand::CreateImm(Val));
1662 }
1663
Jim Grosbach7ce05792011-08-03 23:50:40 +00001664 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1665 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach681460f2011-11-01 01:24:45 +00001666 // If we have an immediate that's not a constant, treat it as a label
1667 // reference needing a fixup. If it is a constant, it's something else
1668 // and we reject it.
1669 if (isImm()) {
1670 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1671 Inst.addOperand(MCOperand::CreateImm(0));
1672 return;
1673 }
1674
Jim Grosbach7ce05792011-08-03 23:50:40 +00001675 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001676 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001677 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1678 // Special case for #-0
1679 if (Val == INT32_MIN) Val = 0;
1680 if (Val < 0) Val = -Val;
1681 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001682 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001683 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001684 }
1685
Jim Grosbacha77295d2011-09-08 22:07:06 +00001686 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1687 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001688 // If we have an immediate that's not a constant, treat it as a label
1689 // reference needing a fixup. If it is a constant, it's something else
1690 // and we reject it.
1691 if (isImm()) {
1692 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1693 Inst.addOperand(MCOperand::CreateImm(0));
1694 return;
1695 }
1696
Jim Grosbache53c87b2011-10-11 15:59:20 +00001697 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1698 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001699 Inst.addOperand(MCOperand::CreateImm(Val));
1700 }
1701
Jim Grosbachb6aed502011-09-09 18:37:27 +00001702 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1703 assert(N == 2 && "Invalid number of operands!");
1704 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001705 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1706 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001707 Inst.addOperand(MCOperand::CreateImm(Val));
1708 }
1709
Jim Grosbach7ce05792011-08-03 23:50:40 +00001710 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1711 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001712 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1713 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001714 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001715 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001716
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001717 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1718 addMemImm8OffsetOperands(Inst, N);
1719 }
1720
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001721 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001722 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001723 }
1724
1725 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1726 assert(N == 2 && "Invalid number of operands!");
1727 // If this is an immediate, it's a label reference.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001728 if (isImm()) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001729 addExpr(Inst, getImm());
1730 Inst.addOperand(MCOperand::CreateImm(0));
1731 return;
1732 }
1733
1734 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001735 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1736 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001737 Inst.addOperand(MCOperand::CreateImm(Val));
1738 }
1739
Jim Grosbach7ce05792011-08-03 23:50:40 +00001740 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1741 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001742 // If this is an immediate, it's a label reference.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001743 if (isImm()) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001744 addExpr(Inst, getImm());
1745 Inst.addOperand(MCOperand::CreateImm(0));
1746 return;
1747 }
1748
1749 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001750 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1751 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001752 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001753 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001754
Jim Grosbach7f739be2011-09-19 22:21:13 +00001755 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1756 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001757 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1758 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001759 }
1760
1761 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1762 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001763 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1764 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001765 }
1766
Jim Grosbach7ce05792011-08-03 23:50:40 +00001767 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1768 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001769 unsigned Val =
1770 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1771 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001772 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1773 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001774 Inst.addOperand(MCOperand::CreateImm(Val));
1775 }
1776
Jim Grosbachab899c12011-09-07 23:10:15 +00001777 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1778 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001779 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1780 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1781 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001782 }
1783
Jim Grosbach7ce05792011-08-03 23:50:40 +00001784 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1785 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001786 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1787 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001788 }
1789
Jim Grosbach60f91a32011-08-19 17:55:24 +00001790 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1791 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001792 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1793 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001794 Inst.addOperand(MCOperand::CreateImm(Val));
1795 }
1796
Jim Grosbach38466302011-08-19 18:55:51 +00001797 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1798 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001799 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1800 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001801 Inst.addOperand(MCOperand::CreateImm(Val));
1802 }
1803
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001804 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1805 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001806 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1807 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001808 Inst.addOperand(MCOperand::CreateImm(Val));
1809 }
1810
Jim Grosbachecd85892011-08-19 18:13:48 +00001811 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1812 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001813 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1814 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001815 Inst.addOperand(MCOperand::CreateImm(Val));
1816 }
1817
Jim Grosbach7ce05792011-08-03 23:50:40 +00001818 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1819 assert(N == 1 && "Invalid number of operands!");
1820 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1821 assert(CE && "non-constant post-idx-imm8 operand!");
1822 int Imm = CE->getValue();
1823 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001824 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001825 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1826 Inst.addOperand(MCOperand::CreateImm(Imm));
1827 }
1828
Jim Grosbach2bd01182011-10-11 21:55:36 +00001829 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1830 assert(N == 1 && "Invalid number of operands!");
1831 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1832 assert(CE && "non-constant post-idx-imm8s4 operand!");
1833 int Imm = CE->getValue();
1834 bool isAdd = Imm >= 0;
1835 if (Imm == INT32_MIN) Imm = 0;
1836 // Immediate is scaled by 4.
1837 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1838 Inst.addOperand(MCOperand::CreateImm(Imm));
1839 }
1840
Jim Grosbach7ce05792011-08-03 23:50:40 +00001841 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1842 assert(N == 2 && "Invalid number of operands!");
1843 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001844 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1845 }
1846
1847 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1848 assert(N == 2 && "Invalid number of operands!");
1849 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1850 // The sign, shift type, and shift amount are encoded in a single operand
1851 // using the AM2 encoding helpers.
1852 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1853 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1854 PostIdxReg.ShiftTy);
1855 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001856 }
1857
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001858 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1859 assert(N == 1 && "Invalid number of operands!");
1860 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1861 }
1862
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001863 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1864 assert(N == 1 && "Invalid number of operands!");
1865 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1866 }
1867
Jim Grosbach6029b6d2011-11-29 23:51:09 +00001868 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach862019c2011-10-18 23:02:30 +00001869 assert(N == 1 && "Invalid number of operands!");
1870 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1871 }
1872
Jim Grosbach7636bf62011-12-02 00:35:16 +00001873 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1874 assert(N == 2 && "Invalid number of operands!");
1875 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1876 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1877 }
1878
Jim Grosbach460a9052011-10-07 23:56:00 +00001879 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1880 assert(N == 1 && "Invalid number of operands!");
1881 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1882 }
1883
1884 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1885 assert(N == 1 && "Invalid number of operands!");
1886 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1887 }
1888
1889 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1890 assert(N == 1 && "Invalid number of operands!");
1891 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1892 }
1893
Jim Grosbach0e387b22011-10-17 22:26:03 +00001894 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1895 assert(N == 1 && "Invalid number of operands!");
1896 // The immediate encodes the type of constant as well as the value.
1897 // Mask in that this is an i8 splat.
1898 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1899 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1900 }
1901
Jim Grosbachea461102011-10-17 23:09:09 +00001902 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1903 assert(N == 1 && "Invalid number of operands!");
1904 // The immediate encodes the type of constant as well as the value.
1905 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1906 unsigned Value = CE->getValue();
1907 if (Value >= 256)
1908 Value = (Value >> 8) | 0xa00;
1909 else
1910 Value |= 0x800;
1911 Inst.addOperand(MCOperand::CreateImm(Value));
1912 }
1913
Jim Grosbach6248a542011-10-18 00:22:00 +00001914 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1915 assert(N == 1 && "Invalid number of operands!");
1916 // The immediate encodes the type of constant as well as the value.
1917 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1918 unsigned Value = CE->getValue();
1919 if (Value >= 256 && Value <= 0xff00)
1920 Value = (Value >> 8) | 0x200;
1921 else if (Value > 0xffff && Value <= 0xff0000)
1922 Value = (Value >> 16) | 0x400;
1923 else if (Value > 0xffffff)
1924 Value = (Value >> 24) | 0x600;
1925 Inst.addOperand(MCOperand::CreateImm(Value));
1926 }
1927
1928 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1929 assert(N == 1 && "Invalid number of operands!");
1930 // The immediate encodes the type of constant as well as the value.
1931 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1932 unsigned Value = CE->getValue();
1933 if (Value >= 256 && Value <= 0xffff)
1934 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1935 else if (Value > 0xffff && Value <= 0xffffff)
1936 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1937 else if (Value > 0xffffff)
1938 Value = (Value >> 24) | 0x600;
1939 Inst.addOperand(MCOperand::CreateImm(Value));
1940 }
1941
Jim Grosbach9b087852011-12-19 23:51:07 +00001942 void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const {
1943 assert(N == 1 && "Invalid number of operands!");
1944 // The immediate encodes the type of constant as well as the value.
1945 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1946 unsigned Value = ~CE->getValue();
1947 if (Value >= 256 && Value <= 0xffff)
1948 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1949 else if (Value > 0xffff && Value <= 0xffffff)
1950 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1951 else if (Value > 0xffffff)
1952 Value = (Value >> 24) | 0x600;
1953 Inst.addOperand(MCOperand::CreateImm(Value));
1954 }
1955
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001956 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1957 assert(N == 1 && "Invalid number of operands!");
1958 // The immediate encodes the type of constant as well as the value.
1959 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1960 uint64_t Value = CE->getValue();
1961 unsigned Imm = 0;
1962 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1963 Imm |= (Value & 1) << i;
1964 }
1965 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1966 }
1967
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001968 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001969
Jim Grosbach89df9962011-08-26 21:43:41 +00001970 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001971 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001972 Op->ITMask.Mask = Mask;
1973 Op->StartLoc = S;
1974 Op->EndLoc = S;
1975 return Op;
1976 }
1977
Chris Lattner3a697562010-10-28 17:20:03 +00001978 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001979 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001980 Op->CC.Val = CC;
1981 Op->StartLoc = S;
1982 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001983 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001984 }
1985
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001986 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001987 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001988 Op->Cop.Val = CopVal;
1989 Op->StartLoc = S;
1990 Op->EndLoc = S;
1991 return Op;
1992 }
1993
1994 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001995 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001996 Op->Cop.Val = CopVal;
1997 Op->StartLoc = S;
1998 Op->EndLoc = S;
1999 return Op;
2000 }
2001
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002002 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
2003 ARMOperand *Op = new ARMOperand(k_CoprocOption);
2004 Op->Cop.Val = Val;
2005 Op->StartLoc = S;
2006 Op->EndLoc = E;
2007 return Op;
2008 }
2009
Jim Grosbachd67641b2010-12-06 18:21:12 +00002010 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002011 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00002012 Op->Reg.RegNum = RegNum;
2013 Op->StartLoc = S;
2014 Op->EndLoc = S;
2015 return Op;
2016 }
2017
Chris Lattner3a697562010-10-28 17:20:03 +00002018 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002019 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00002020 Op->Tok.Data = Str.data();
2021 Op->Tok.Length = Str.size();
2022 Op->StartLoc = S;
2023 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00002024 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002025 }
2026
Bill Wendling50d0f582010-11-18 23:43:05 +00002027 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002028 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00002029 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00002030 Op->StartLoc = S;
2031 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002032 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002033 }
2034
Jim Grosbache8606dc2011-07-13 17:50:29 +00002035 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
2036 unsigned SrcReg,
2037 unsigned ShiftReg,
2038 unsigned ShiftImm,
2039 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002040 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002041 Op->RegShiftedReg.ShiftTy = ShTy;
2042 Op->RegShiftedReg.SrcReg = SrcReg;
2043 Op->RegShiftedReg.ShiftReg = ShiftReg;
2044 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002045 Op->StartLoc = S;
2046 Op->EndLoc = E;
2047 return Op;
2048 }
2049
Owen Anderson92a20222011-07-21 18:54:16 +00002050 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
2051 unsigned SrcReg,
2052 unsigned ShiftImm,
2053 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002054 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002055 Op->RegShiftedImm.ShiftTy = ShTy;
2056 Op->RegShiftedImm.SrcReg = SrcReg;
2057 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00002058 Op->StartLoc = S;
2059 Op->EndLoc = E;
2060 return Op;
2061 }
2062
Jim Grosbach580f4a92011-07-25 22:20:28 +00002063 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002064 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002065 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00002066 Op->ShifterImm.isASR = isASR;
2067 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00002068 Op->StartLoc = S;
2069 Op->EndLoc = E;
2070 return Op;
2071 }
2072
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002073 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002074 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002075 Op->RotImm.Imm = Imm;
2076 Op->StartLoc = S;
2077 Op->EndLoc = E;
2078 return Op;
2079 }
2080
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002081 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
2082 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002083 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002084 Op->Bitfield.LSB = LSB;
2085 Op->Bitfield.Width = Width;
2086 Op->StartLoc = S;
2087 Op->EndLoc = E;
2088 return Op;
2089 }
2090
Bill Wendling7729e062010-11-09 22:44:22 +00002091 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00002092 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002093 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002094 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002095
Jim Grosbachd300b942011-09-13 22:56:44 +00002096 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002097 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00002098 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00002099 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002100 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002101
2102 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00002103 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002104 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00002105 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00002106 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002107 Op->StartLoc = StartLoc;
2108 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00002109 return Op;
2110 }
2111
Jim Grosbach862019c2011-10-18 23:02:30 +00002112 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002113 bool isDoubleSpaced, SMLoc S, SMLoc E) {
Jim Grosbach862019c2011-10-18 23:02:30 +00002114 ARMOperand *Op = new ARMOperand(k_VectorList);
2115 Op->VectorList.RegNum = RegNum;
2116 Op->VectorList.Count = Count;
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002117 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach862019c2011-10-18 23:02:30 +00002118 Op->StartLoc = S;
2119 Op->EndLoc = E;
2120 return Op;
2121 }
2122
Jim Grosbach98b05a52011-11-30 01:09:44 +00002123 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002124 bool isDoubleSpaced,
Jim Grosbach98b05a52011-11-30 01:09:44 +00002125 SMLoc S, SMLoc E) {
2126 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
2127 Op->VectorList.RegNum = RegNum;
2128 Op->VectorList.Count = Count;
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002129 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002130 Op->StartLoc = S;
2131 Op->EndLoc = E;
2132 return Op;
2133 }
2134
Jim Grosbach7636bf62011-12-02 00:35:16 +00002135 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002136 unsigned Index,
2137 bool isDoubleSpaced,
2138 SMLoc S, SMLoc E) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002139 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
2140 Op->VectorList.RegNum = RegNum;
2141 Op->VectorList.Count = Count;
2142 Op->VectorList.LaneIndex = Index;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002143 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002144 Op->StartLoc = S;
2145 Op->EndLoc = E;
2146 return Op;
2147 }
2148
Jim Grosbach460a9052011-10-07 23:56:00 +00002149 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
2150 MCContext &Ctx) {
2151 ARMOperand *Op = new ARMOperand(k_VectorIndex);
2152 Op->VectorIndex.Val = Idx;
2153 Op->StartLoc = S;
2154 Op->EndLoc = E;
2155 return Op;
2156 }
2157
Chris Lattner3a697562010-10-28 17:20:03 +00002158 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002159 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00002160 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00002161 Op->StartLoc = S;
2162 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002163 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00002164 }
2165
Jim Grosbach7ce05792011-08-03 23:50:40 +00002166 static ARMOperand *CreateMem(unsigned BaseRegNum,
2167 const MCConstantExpr *OffsetImm,
2168 unsigned OffsetRegNum,
2169 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002170 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00002171 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002172 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00002173 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002174 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00002175 Op->Memory.BaseRegNum = BaseRegNum;
2176 Op->Memory.OffsetImm = OffsetImm;
2177 Op->Memory.OffsetRegNum = OffsetRegNum;
2178 Op->Memory.ShiftType = ShiftType;
2179 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00002180 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00002181 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002182 Op->StartLoc = S;
2183 Op->EndLoc = E;
2184 return Op;
2185 }
Jim Grosbach16c74252010-10-29 14:46:02 +00002186
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002187 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
2188 ARM_AM::ShiftOpc ShiftTy,
2189 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002190 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002191 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002192 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002193 Op->PostIdxReg.isAdd = isAdd;
2194 Op->PostIdxReg.ShiftTy = ShiftTy;
2195 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00002196 Op->StartLoc = S;
2197 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002198 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002199 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002200
2201 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002202 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002203 Op->MBOpt.Val = Opt;
2204 Op->StartLoc = S;
2205 Op->EndLoc = S;
2206 return Op;
2207 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002208
2209 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002210 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002211 Op->IFlags.Val = IFlags;
2212 Op->StartLoc = S;
2213 Op->EndLoc = S;
2214 return Op;
2215 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002216
2217 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002218 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002219 Op->MMask.Val = MMask;
2220 Op->StartLoc = S;
2221 Op->EndLoc = S;
2222 return Op;
2223 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002224};
2225
2226} // end anonymous namespace.
2227
Jim Grosbachb7f689b2011-07-13 15:34:57 +00002228void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002229 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002230 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00002231 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002232 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002233 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00002234 OS << "<ccout " << getReg() << ">";
2235 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002236 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002237 static const char *MaskStr[] = {
2238 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2239 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2240 };
Jim Grosbach89df9962011-08-26 21:43:41 +00002241 assert((ITMask.Mask & 0xf) == ITMask.Mask);
2242 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2243 break;
2244 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002245 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002246 OS << "<coprocessor number: " << getCoproc() << ">";
2247 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002248 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002249 OS << "<coprocessor register: " << getCoproc() << ">";
2250 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002251 case k_CoprocOption:
2252 OS << "<coprocessor option: " << CoprocOption.Val << ">";
2253 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002254 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002255 OS << "<mask: " << getMSRMask() << ">";
2256 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002257 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002258 getImm()->print(OS);
2259 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002260 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002261 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2262 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002263 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002264 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00002265 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002266 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002267 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002268 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002269 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2270 << PostIdxReg.RegNum;
2271 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2272 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2273 << PostIdxReg.ShiftImm;
2274 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00002275 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002276 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002277 OS << "<ARM_PROC::";
2278 unsigned IFlags = getProcIFlags();
2279 for (int i=2; i >= 0; --i)
2280 if (IFlags & (1 << i))
2281 OS << ARM_PROC::IFlagsToString(1 << i);
2282 OS << ">";
2283 break;
2284 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002285 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00002286 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002287 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002288 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00002289 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2290 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00002291 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002292 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00002293 OS << "<so_reg_reg "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002294 << RegShiftedReg.SrcReg << " "
2295 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2296 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson00828302011-03-18 22:50:18 +00002297 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002298 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00002299 OS << "<so_reg_imm "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002300 << RegShiftedImm.SrcReg << " "
2301 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2302 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Anderson92a20222011-07-21 18:54:16 +00002303 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002304 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002305 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2306 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002307 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002308 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2309 << ", width: " << Bitfield.Width << ">";
2310 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002311 case k_RegisterList:
2312 case k_DPRRegisterList:
2313 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00002314 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002315
Bill Wendling5fa22a12010-11-09 23:28:44 +00002316 const SmallVectorImpl<unsigned> &RegList = getRegList();
2317 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002318 I = RegList.begin(), E = RegList.end(); I != E; ) {
2319 OS << *I;
2320 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002321 }
2322
2323 OS << ">";
2324 break;
2325 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002326 case k_VectorList:
2327 OS << "<vector_list " << VectorList.Count << " * "
2328 << VectorList.RegNum << ">";
2329 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002330 case k_VectorListAllLanes:
2331 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2332 << VectorList.RegNum << ">";
2333 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002334 case k_VectorListIndexed:
2335 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2336 << VectorList.Count << " * " << VectorList.RegNum << ">";
2337 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002338 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002339 OS << "'" << getToken() << "'";
2340 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00002341 case k_VectorIndex:
2342 OS << "<vectorindex " << getVectorIndex() << ">";
2343 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002344 }
2345}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00002346
2347/// @name Auto-generated Match Functions
2348/// {
2349
2350static unsigned MatchRegisterName(StringRef Name);
2351
2352/// }
2353
Bob Wilson69df7232011-02-03 21:46:10 +00002354bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2355 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbacha39cda72011-12-14 02:16:11 +00002356 StartLoc = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002357 RegNo = tryParseRegister();
Jim Grosbacha39cda72011-12-14 02:16:11 +00002358 EndLoc = Parser.getTok().getLoc();
Roman Divackybf755322011-01-27 17:14:22 +00002359
2360 return (RegNo == (unsigned)-1);
2361}
2362
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002363/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002364/// and if it is a register name the token is eaten and the register number is
2365/// returned. Otherwise return -1.
2366///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002367int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002368 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002369 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002370
Benjamin Kramer59085362011-11-06 20:37:06 +00002371 std::string lowerCase = Tok.getString().lower();
Owen Anderson0c9f2502011-01-13 22:50:36 +00002372 unsigned RegNum = MatchRegisterName(lowerCase);
2373 if (!RegNum) {
2374 RegNum = StringSwitch<unsigned>(lowerCase)
2375 .Case("r13", ARM::SP)
2376 .Case("r14", ARM::LR)
2377 .Case("r15", ARM::PC)
2378 .Case("ip", ARM::R12)
Jim Grosbach40e28552011-12-08 19:27:38 +00002379 // Additional register name aliases for 'gas' compatibility.
2380 .Case("a1", ARM::R0)
2381 .Case("a2", ARM::R1)
2382 .Case("a3", ARM::R2)
2383 .Case("a4", ARM::R3)
2384 .Case("v1", ARM::R4)
2385 .Case("v2", ARM::R5)
2386 .Case("v3", ARM::R6)
2387 .Case("v4", ARM::R7)
2388 .Case("v5", ARM::R8)
2389 .Case("v6", ARM::R9)
2390 .Case("v7", ARM::R10)
2391 .Case("v8", ARM::R11)
2392 .Case("sb", ARM::R9)
2393 .Case("sl", ARM::R10)
2394 .Case("fp", ARM::R11)
Owen Anderson0c9f2502011-01-13 22:50:36 +00002395 .Default(0);
2396 }
Jim Grosbacha39cda72011-12-14 02:16:11 +00002397 if (!RegNum) {
Jim Grosbachaee718b2011-12-20 23:11:00 +00002398 // Check for aliases registered via .req. Canonicalize to lower case.
2399 // That's more consistent since register names are case insensitive, and
2400 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2401 StringMap<unsigned>::const_iterator Entry = RegisterReqs.find(lowerCase);
Jim Grosbacha39cda72011-12-14 02:16:11 +00002402 // If no match, return failure.
2403 if (Entry == RegisterReqs.end())
2404 return -1;
2405 Parser.Lex(); // Eat identifier token.
2406 return Entry->getValue();
2407 }
Bob Wilson69df7232011-02-03 21:46:10 +00002408
Chris Lattnere5658fa2010-10-30 04:09:10 +00002409 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002410
Chris Lattnere5658fa2010-10-30 04:09:10 +00002411 return RegNum;
2412}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002413
Jim Grosbach19906722011-07-13 18:49:30 +00002414// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2415// If a recoverable error occurs, return 1. If an irrecoverable error
2416// occurs, return -1. An irrecoverable error is one where tokens have been
2417// consumed in the process of trying to parse the shifter (i.e., when it is
2418// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002419int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002420 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2421 SMLoc S = Parser.getTok().getLoc();
2422 const AsmToken &Tok = Parser.getTok();
2423 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2424
Benjamin Kramer59085362011-11-06 20:37:06 +00002425 std::string lowerCase = Tok.getString().lower();
Owen Anderson00828302011-03-18 22:50:18 +00002426 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbachaf4edea2011-12-07 23:40:58 +00002427 .Case("asl", ARM_AM::lsl)
Owen Anderson00828302011-03-18 22:50:18 +00002428 .Case("lsl", ARM_AM::lsl)
2429 .Case("lsr", ARM_AM::lsr)
2430 .Case("asr", ARM_AM::asr)
2431 .Case("ror", ARM_AM::ror)
2432 .Case("rrx", ARM_AM::rrx)
2433 .Default(ARM_AM::no_shift);
2434
2435 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002436 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002437
Jim Grosbache8606dc2011-07-13 17:50:29 +00002438 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002439
Jim Grosbache8606dc2011-07-13 17:50:29 +00002440 // The source register for the shift has already been added to the
2441 // operand list, so we need to pop it off and combine it into the shifted
2442 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002443 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002444 if (!PrevOp->isReg())
2445 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2446 int SrcReg = PrevOp->getReg();
2447 int64_t Imm = 0;
2448 int ShiftReg = 0;
2449 if (ShiftTy == ARM_AM::rrx) {
2450 // RRX Doesn't have an explicit shift amount. The encoder expects
2451 // the shift register to be the same as the source register. Seems odd,
2452 // but OK.
2453 ShiftReg = SrcReg;
2454 } else {
2455 // Figure out if this is shifted by a constant or a register (for non-RRX).
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00002456 if (Parser.getTok().is(AsmToken::Hash) ||
2457 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbache8606dc2011-07-13 17:50:29 +00002458 Parser.Lex(); // Eat hash.
2459 SMLoc ImmLoc = Parser.getTok().getLoc();
2460 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002461 if (getParser().ParseExpression(ShiftExpr)) {
2462 Error(ImmLoc, "invalid immediate shift value");
2463 return -1;
2464 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002465 // The expression must be evaluatable as an immediate.
2466 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002467 if (!CE) {
2468 Error(ImmLoc, "invalid immediate shift value");
2469 return -1;
2470 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002471 // Range check the immediate.
2472 // lsl, ror: 0 <= imm <= 31
2473 // lsr, asr: 0 <= imm <= 32
2474 Imm = CE->getValue();
2475 if (Imm < 0 ||
2476 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2477 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002478 Error(ImmLoc, "immediate shift value out of range");
2479 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002480 }
Jim Grosbachde626ad2011-12-22 17:37:00 +00002481 // shift by zero is a nop. Always send it through as lsl.
2482 // ('as' compatibility)
2483 if (Imm == 0)
2484 ShiftTy = ARM_AM::lsl;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002485 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002486 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002487 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002488 if (ShiftReg == -1) {
2489 Error (L, "expected immediate or register in shift operand");
2490 return -1;
2491 }
2492 } else {
2493 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002494 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002495 return -1;
2496 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002497 }
2498
Owen Anderson92a20222011-07-21 18:54:16 +00002499 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2500 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002501 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002502 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002503 else
2504 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2505 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002506
Jim Grosbach19906722011-07-13 18:49:30 +00002507 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002508}
2509
2510
Bill Wendling50d0f582010-11-18 23:43:05 +00002511/// Try to parse a register name. The token must be an Identifier when called.
2512/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2513/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002514///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002515/// TODO this is likely to change to allow different register types and or to
2516/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002517bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002518tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002519 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002520 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002521 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002522 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002523
Bill Wendling50d0f582010-11-18 23:43:05 +00002524 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002525
Chris Lattnere5658fa2010-10-30 04:09:10 +00002526 const AsmToken &ExclaimTok = Parser.getTok();
2527 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002528 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2529 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002530 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002531 return false;
2532 }
2533
2534 // Also check for an index operand. This is only legal for vector registers,
2535 // but that'll get caught OK in operand matching, so we don't need to
2536 // explicitly filter everything else out here.
2537 if (Parser.getTok().is(AsmToken::LBrac)) {
2538 SMLoc SIdx = Parser.getTok().getLoc();
2539 Parser.Lex(); // Eat left bracket token.
2540
2541 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002542 if (getParser().ParseExpression(ImmVal))
2543 return MatchOperand_ParseFail;
2544 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2545 if (!MCE) {
2546 TokError("immediate value expected for vector index");
2547 return MatchOperand_ParseFail;
2548 }
2549
2550 SMLoc E = Parser.getTok().getLoc();
2551 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2552 Error(E, "']' expected");
2553 return MatchOperand_ParseFail;
2554 }
2555
2556 Parser.Lex(); // Eat right bracket token.
2557
2558 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2559 SIdx, E,
2560 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002561 }
2562
Bill Wendling50d0f582010-11-18 23:43:05 +00002563 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002564}
2565
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002566/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2567/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2568/// "c5", ...
2569static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002570 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2571 // but efficient.
2572 switch (Name.size()) {
David Blaikie4d6ccb52012-01-20 21:51:11 +00002573 default: return -1;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002574 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002575 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002576 return -1;
2577 switch (Name[1]) {
2578 default: return -1;
2579 case '0': return 0;
2580 case '1': return 1;
2581 case '2': return 2;
2582 case '3': return 3;
2583 case '4': return 4;
2584 case '5': return 5;
2585 case '6': return 6;
2586 case '7': return 7;
2587 case '8': return 8;
2588 case '9': return 9;
2589 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002590 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002591 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002592 return -1;
2593 switch (Name[2]) {
2594 default: return -1;
2595 case '0': return 10;
2596 case '1': return 11;
2597 case '2': return 12;
2598 case '3': return 13;
2599 case '4': return 14;
2600 case '5': return 15;
2601 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002602 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002603}
2604
Jim Grosbach89df9962011-08-26 21:43:41 +00002605/// parseITCondCode - Try to parse a condition code for an IT instruction.
2606ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2607parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2608 SMLoc S = Parser.getTok().getLoc();
2609 const AsmToken &Tok = Parser.getTok();
2610 if (!Tok.is(AsmToken::Identifier))
2611 return MatchOperand_NoMatch;
2612 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2613 .Case("eq", ARMCC::EQ)
2614 .Case("ne", ARMCC::NE)
2615 .Case("hs", ARMCC::HS)
2616 .Case("cs", ARMCC::HS)
2617 .Case("lo", ARMCC::LO)
2618 .Case("cc", ARMCC::LO)
2619 .Case("mi", ARMCC::MI)
2620 .Case("pl", ARMCC::PL)
2621 .Case("vs", ARMCC::VS)
2622 .Case("vc", ARMCC::VC)
2623 .Case("hi", ARMCC::HI)
2624 .Case("ls", ARMCC::LS)
2625 .Case("ge", ARMCC::GE)
2626 .Case("lt", ARMCC::LT)
2627 .Case("gt", ARMCC::GT)
2628 .Case("le", ARMCC::LE)
2629 .Case("al", ARMCC::AL)
2630 .Default(~0U);
2631 if (CC == ~0U)
2632 return MatchOperand_NoMatch;
2633 Parser.Lex(); // Eat the token.
2634
2635 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2636
2637 return MatchOperand_Success;
2638}
2639
Jim Grosbach43904292011-07-25 20:14:50 +00002640/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002641/// token must be an Identifier when called, and if it is a coprocessor
2642/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002643ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002644parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002645 SMLoc S = Parser.getTok().getLoc();
2646 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002647 if (Tok.isNot(AsmToken::Identifier))
2648 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002649
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002650 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002651 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002652 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002653
2654 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002655 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002656 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002657}
2658
Jim Grosbach43904292011-07-25 20:14:50 +00002659/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002660/// token must be an Identifier when called, and if it is a coprocessor
2661/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002662ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002663parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002664 SMLoc S = Parser.getTok().getLoc();
2665 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002666 if (Tok.isNot(AsmToken::Identifier))
2667 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002668
2669 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2670 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002671 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002672
2673 Parser.Lex(); // Eat identifier token.
2674 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002675 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002676}
2677
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002678/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2679/// coproc_option : '{' imm0_255 '}'
2680ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2681parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2682 SMLoc S = Parser.getTok().getLoc();
2683
2684 // If this isn't a '{', this isn't a coprocessor immediate operand.
2685 if (Parser.getTok().isNot(AsmToken::LCurly))
2686 return MatchOperand_NoMatch;
2687 Parser.Lex(); // Eat the '{'
2688
2689 const MCExpr *Expr;
2690 SMLoc Loc = Parser.getTok().getLoc();
2691 if (getParser().ParseExpression(Expr)) {
2692 Error(Loc, "illegal expression");
2693 return MatchOperand_ParseFail;
2694 }
2695 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2696 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2697 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2698 return MatchOperand_ParseFail;
2699 }
2700 int Val = CE->getValue();
2701
2702 // Check for and consume the closing '}'
2703 if (Parser.getTok().isNot(AsmToken::RCurly))
2704 return MatchOperand_ParseFail;
2705 SMLoc E = Parser.getTok().getLoc();
2706 Parser.Lex(); // Eat the '}'
2707
2708 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2709 return MatchOperand_Success;
2710}
2711
Jim Grosbachd0588e22011-09-14 18:08:35 +00002712// For register list parsing, we need to map from raw GPR register numbering
2713// to the enumeration values. The enumeration values aren't sorted by
2714// register number due to our using "sp", "lr" and "pc" as canonical names.
2715static unsigned getNextRegister(unsigned Reg) {
2716 // If this is a GPR, we need to do it manually, otherwise we can rely
2717 // on the sort ordering of the enumeration since the other reg-classes
2718 // are sane.
2719 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2720 return Reg + 1;
2721 switch(Reg) {
2722 default: assert(0 && "Invalid GPR number!");
2723 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2724 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2725 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2726 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2727 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2728 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2729 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2730 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2731 }
2732}
2733
Jim Grosbachce485e72011-11-11 21:27:40 +00002734// Return the low-subreg of a given Q register.
2735static unsigned getDRegFromQReg(unsigned QReg) {
2736 switch (QReg) {
2737 default: llvm_unreachable("expected a Q register!");
2738 case ARM::Q0: return ARM::D0;
2739 case ARM::Q1: return ARM::D2;
2740 case ARM::Q2: return ARM::D4;
2741 case ARM::Q3: return ARM::D6;
2742 case ARM::Q4: return ARM::D8;
2743 case ARM::Q5: return ARM::D10;
2744 case ARM::Q6: return ARM::D12;
2745 case ARM::Q7: return ARM::D14;
2746 case ARM::Q8: return ARM::D16;
Jim Grosbach25e0a872011-11-15 21:01:30 +00002747 case ARM::Q9: return ARM::D18;
Jim Grosbachce485e72011-11-11 21:27:40 +00002748 case ARM::Q10: return ARM::D20;
2749 case ARM::Q11: return ARM::D22;
2750 case ARM::Q12: return ARM::D24;
2751 case ARM::Q13: return ARM::D26;
2752 case ARM::Q14: return ARM::D28;
2753 case ARM::Q15: return ARM::D30;
2754 }
2755}
2756
Jim Grosbachd0588e22011-09-14 18:08:35 +00002757/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002758bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002759parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002760 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002761 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002762 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002763 Parser.Lex(); // Eat '{' token.
2764 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002765
Jim Grosbachd0588e22011-09-14 18:08:35 +00002766 // Check the first register in the list to see what register class
2767 // this is a list of.
2768 int Reg = tryParseRegister();
2769 if (Reg == -1)
2770 return Error(RegLoc, "register expected");
2771
Jim Grosbachce485e72011-11-11 21:27:40 +00002772 // The reglist instructions have at most 16 registers, so reserve
2773 // space for that many.
2774 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2775
2776 // Allow Q regs and just interpret them as the two D sub-registers.
2777 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2778 Reg = getDRegFromQReg(Reg);
2779 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2780 ++Reg;
2781 }
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002782 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002783 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2784 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2785 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2786 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2787 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2788 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2789 else
2790 return Error(RegLoc, "invalid register in register list");
2791
Jim Grosbachce485e72011-11-11 21:27:40 +00002792 // Store the register.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002793 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002794
Jim Grosbachd0588e22011-09-14 18:08:35 +00002795 // This starts immediately after the first register token in the list,
2796 // so we can see either a comma or a minus (range separator) as a legal
2797 // next token.
2798 while (Parser.getTok().is(AsmToken::Comma) ||
2799 Parser.getTok().is(AsmToken::Minus)) {
2800 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache43862b2011-11-15 23:19:15 +00002801 Parser.Lex(); // Eat the minus.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002802 SMLoc EndLoc = Parser.getTok().getLoc();
2803 int EndReg = tryParseRegister();
2804 if (EndReg == -1)
2805 return Error(EndLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002806 // Allow Q regs and just interpret them as the two D sub-registers.
2807 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2808 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002809 // If the register is the same as the start reg, there's nothing
2810 // more to do.
2811 if (Reg == EndReg)
2812 continue;
2813 // The register must be in the same register class as the first.
2814 if (!RC->contains(EndReg))
2815 return Error(EndLoc, "invalid register in register list");
2816 // Ranges must go from low to high.
2817 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2818 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002819
Jim Grosbachd0588e22011-09-14 18:08:35 +00002820 // Add all the registers in the range to the register list.
2821 while (Reg != EndReg) {
2822 Reg = getNextRegister(Reg);
2823 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2824 }
2825 continue;
2826 }
2827 Parser.Lex(); // Eat the comma.
2828 RegLoc = Parser.getTok().getLoc();
2829 int OldReg = Reg;
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002830 const AsmToken RegTok = Parser.getTok();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002831 Reg = tryParseRegister();
2832 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002833 return Error(RegLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002834 // Allow Q regs and just interpret them as the two D sub-registers.
2835 bool isQReg = false;
2836 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2837 Reg = getDRegFromQReg(Reg);
2838 isQReg = true;
2839 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002840 // The register must be in the same register class as the first.
2841 if (!RC->contains(Reg))
2842 return Error(RegLoc, "invalid register in register list");
2843 // List must be monotonically increasing.
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002844 if (getARMRegisterNumbering(Reg) < getARMRegisterNumbering(OldReg))
Jim Grosbachd0588e22011-09-14 18:08:35 +00002845 return Error(RegLoc, "register list not in ascending order");
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002846 if (getARMRegisterNumbering(Reg) == getARMRegisterNumbering(OldReg)) {
2847 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
2848 ") in register list");
2849 continue;
2850 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002851 // VFP register lists must also be contiguous.
2852 // It's OK to use the enumeration values directly here rather, as the
2853 // VFP register classes have the enum sorted properly.
2854 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2855 Reg != OldReg + 1)
2856 return Error(RegLoc, "non-contiguous register range");
2857 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbachce485e72011-11-11 21:27:40 +00002858 if (isQReg)
2859 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002860 }
2861
Jim Grosbachd0588e22011-09-14 18:08:35 +00002862 SMLoc E = Parser.getTok().getLoc();
2863 if (Parser.getTok().isNot(AsmToken::RCurly))
2864 return Error(E, "'}' expected");
2865 Parser.Lex(); // Eat '}' token.
2866
Jim Grosbach27debd62011-12-13 21:48:29 +00002867 // Push the register list operand.
Bill Wendling50d0f582010-11-18 23:43:05 +00002868 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
Jim Grosbach27debd62011-12-13 21:48:29 +00002869
2870 // The ARM system instruction variants for LDM/STM have a '^' token here.
2871 if (Parser.getTok().is(AsmToken::Caret)) {
2872 Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
2873 Parser.Lex(); // Eat '^' token.
2874 }
2875
Bill Wendling50d0f582010-11-18 23:43:05 +00002876 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002877}
2878
Jim Grosbach98b05a52011-11-30 01:09:44 +00002879// Helper function to parse the lane index for vector lists.
2880ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach7636bf62011-12-02 00:35:16 +00002881parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2882 Index = 0; // Always return a defined index value.
Jim Grosbach98b05a52011-11-30 01:09:44 +00002883 if (Parser.getTok().is(AsmToken::LBrac)) {
2884 Parser.Lex(); // Eat the '['.
2885 if (Parser.getTok().is(AsmToken::RBrac)) {
2886 // "Dn[]" is the 'all lanes' syntax.
2887 LaneKind = AllLanes;
2888 Parser.Lex(); // Eat the ']'.
2889 return MatchOperand_Success;
2890 }
Jim Grosbachc9313252011-12-21 01:19:23 +00002891 const MCExpr *LaneIndex;
2892 SMLoc Loc = Parser.getTok().getLoc();
2893 if (getParser().ParseExpression(LaneIndex)) {
2894 Error(Loc, "illegal expression");
2895 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002896 }
Jim Grosbachc9313252011-12-21 01:19:23 +00002897 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LaneIndex);
2898 if (!CE) {
2899 Error(Loc, "lane index must be empty or an integer");
2900 return MatchOperand_ParseFail;
2901 }
2902 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2903 Error(Parser.getTok().getLoc(), "']' expected");
2904 return MatchOperand_ParseFail;
2905 }
2906 Parser.Lex(); // Eat the ']'.
2907 int64_t Val = CE->getValue();
2908
2909 // FIXME: Make this range check context sensitive for .8, .16, .32.
2910 if (Val < 0 || Val > 7) {
2911 Error(Parser.getTok().getLoc(), "lane index out of range");
2912 return MatchOperand_ParseFail;
2913 }
2914 Index = Val;
2915 LaneKind = IndexedLane;
2916 return MatchOperand_Success;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002917 }
2918 LaneKind = NoLanes;
2919 return MatchOperand_Success;
2920}
2921
Jim Grosbach862019c2011-10-18 23:02:30 +00002922// parse a vector register list
2923ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2924parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002925 VectorLaneTy LaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002926 unsigned LaneIndex;
Jim Grosbach5c984e42011-11-15 21:45:55 +00002927 SMLoc S = Parser.getTok().getLoc();
2928 // As an extension (to match gas), support a plain D register or Q register
2929 // (without encosing curly braces) as a single or double entry list,
2930 // respectively.
2931 if (Parser.getTok().is(AsmToken::Identifier)) {
2932 int Reg = tryParseRegister();
2933 if (Reg == -1)
2934 return MatchOperand_NoMatch;
2935 SMLoc E = Parser.getTok().getLoc();
2936 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002937 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002938 if (Res != MatchOperand_Success)
2939 return Res;
2940 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002941 case NoLanes:
2942 E = Parser.getTok().getLoc();
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002943 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002944 break;
2945 case AllLanes:
2946 E = Parser.getTok().getLoc();
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002947 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false,
2948 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002949 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002950 case IndexedLane:
2951 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002952 LaneIndex,
2953 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00002954 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002955 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002956 return MatchOperand_Success;
2957 }
2958 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2959 Reg = getDRegFromQReg(Reg);
Jim Grosbach7636bf62011-12-02 00:35:16 +00002960 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002961 if (Res != MatchOperand_Success)
2962 return Res;
2963 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002964 case NoLanes:
2965 E = Parser.getTok().getLoc();
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002966 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002967 break;
2968 case AllLanes:
2969 E = Parser.getTok().getLoc();
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002970 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, false,
2971 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002972 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002973 case IndexedLane:
2974 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002975 LaneIndex,
2976 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00002977 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002978 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002979 return MatchOperand_Success;
2980 }
2981 Error(S, "vector register expected");
2982 return MatchOperand_ParseFail;
2983 }
2984
2985 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbach862019c2011-10-18 23:02:30 +00002986 return MatchOperand_NoMatch;
2987
Jim Grosbach862019c2011-10-18 23:02:30 +00002988 Parser.Lex(); // Eat '{' token.
2989 SMLoc RegLoc = Parser.getTok().getLoc();
2990
2991 int Reg = tryParseRegister();
2992 if (Reg == -1) {
2993 Error(RegLoc, "register expected");
2994 return MatchOperand_ParseFail;
2995 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002996 unsigned Count = 1;
Jim Grosbach276ed032011-12-15 21:54:55 +00002997 int Spacing = 0;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002998 unsigned FirstReg = Reg;
2999 // The list is of D registers, but we also allow Q regs and just interpret
3000 // them as the two D sub-registers.
3001 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
3002 FirstReg = Reg = getDRegFromQReg(Reg);
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003003 Spacing = 1; // double-spacing requires explicit D registers, otherwise
3004 // it's ambiguous with four-register single spaced.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003005 ++Reg;
3006 ++Count;
3007 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00003008 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003009 return MatchOperand_ParseFail;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003010
Jim Grosbache43862b2011-11-15 23:19:15 +00003011 while (Parser.getTok().is(AsmToken::Comma) ||
3012 Parser.getTok().is(AsmToken::Minus)) {
3013 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003014 if (!Spacing)
3015 Spacing = 1; // Register range implies a single spaced list.
3016 else if (Spacing == 2) {
3017 Error(Parser.getTok().getLoc(),
3018 "sequential registers in double spaced list");
3019 return MatchOperand_ParseFail;
3020 }
Jim Grosbache43862b2011-11-15 23:19:15 +00003021 Parser.Lex(); // Eat the minus.
3022 SMLoc EndLoc = Parser.getTok().getLoc();
3023 int EndReg = tryParseRegister();
3024 if (EndReg == -1) {
3025 Error(EndLoc, "register expected");
3026 return MatchOperand_ParseFail;
3027 }
3028 // Allow Q regs and just interpret them as the two D sub-registers.
3029 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
3030 EndReg = getDRegFromQReg(EndReg) + 1;
3031 // If the register is the same as the start reg, there's nothing
3032 // more to do.
3033 if (Reg == EndReg)
3034 continue;
3035 // The register must be in the same register class as the first.
3036 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
3037 Error(EndLoc, "invalid register in register list");
3038 return MatchOperand_ParseFail;
3039 }
3040 // Ranges must go from low to high.
3041 if (Reg > EndReg) {
3042 Error(EndLoc, "bad range in register list");
3043 return MatchOperand_ParseFail;
3044 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00003045 // Parse the lane specifier if present.
3046 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003047 unsigned NextLaneIndex;
3048 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003049 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003050 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003051 Error(EndLoc, "mismatched lane index in register list");
3052 return MatchOperand_ParseFail;
3053 }
3054 EndLoc = Parser.getTok().getLoc();
Jim Grosbache43862b2011-11-15 23:19:15 +00003055
3056 // Add all the registers in the range to the register list.
3057 Count += EndReg - Reg;
3058 Reg = EndReg;
3059 continue;
3060 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003061 Parser.Lex(); // Eat the comma.
3062 RegLoc = Parser.getTok().getLoc();
3063 int OldReg = Reg;
3064 Reg = tryParseRegister();
3065 if (Reg == -1) {
3066 Error(RegLoc, "register expected");
3067 return MatchOperand_ParseFail;
3068 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003069 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00003070 // It's OK to use the enumeration values directly here rather, as the
3071 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003072 //
3073 // The list is of D registers, but we also allow Q regs and just interpret
3074 // them as the two D sub-registers.
3075 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003076 if (!Spacing)
3077 Spacing = 1; // Register range implies a single spaced list.
3078 else if (Spacing == 2) {
3079 Error(RegLoc,
3080 "invalid register in double-spaced list (must be 'D' register')");
3081 return MatchOperand_ParseFail;
3082 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003083 Reg = getDRegFromQReg(Reg);
3084 if (Reg != OldReg + 1) {
3085 Error(RegLoc, "non-contiguous register range");
3086 return MatchOperand_ParseFail;
3087 }
3088 ++Reg;
3089 Count += 2;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003090 // Parse the lane specifier if present.
3091 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003092 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003093 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003094 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003095 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003096 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003097 Error(EndLoc, "mismatched lane index in register list");
3098 return MatchOperand_ParseFail;
3099 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003100 continue;
3101 }
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003102 // Normal D register.
3103 // Figure out the register spacing (single or double) of the list if
3104 // we don't know it already.
3105 if (!Spacing)
3106 Spacing = 1 + (Reg == OldReg + 2);
3107
3108 // Just check that it's contiguous and keep going.
3109 if (Reg != OldReg + Spacing) {
Jim Grosbach862019c2011-10-18 23:02:30 +00003110 Error(RegLoc, "non-contiguous register range");
3111 return MatchOperand_ParseFail;
3112 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003113 ++Count;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003114 // Parse the lane specifier if present.
3115 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003116 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003117 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003118 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003119 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003120 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003121 Error(EndLoc, "mismatched lane index in register list");
3122 return MatchOperand_ParseFail;
3123 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003124 }
3125
3126 SMLoc E = Parser.getTok().getLoc();
3127 if (Parser.getTok().isNot(AsmToken::RCurly)) {
3128 Error(E, "'}' expected");
3129 return MatchOperand_ParseFail;
3130 }
3131 Parser.Lex(); // Eat '}' token.
3132
Jim Grosbach98b05a52011-11-30 01:09:44 +00003133 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003134 case NoLanes:
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003135 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count,
3136 (Spacing == 2), S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003137 break;
3138 case AllLanes:
3139 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00003140 (Spacing == 2),
Jim Grosbach98b05a52011-11-30 01:09:44 +00003141 S, E));
3142 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003143 case IndexedLane:
3144 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00003145 LaneIndex,
3146 (Spacing == 2),
3147 S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00003148 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003149 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003150 return MatchOperand_Success;
3151}
3152
Jim Grosbach43904292011-07-25 20:14:50 +00003153/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00003154ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003155parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003156 SMLoc S = Parser.getTok().getLoc();
3157 const AsmToken &Tok = Parser.getTok();
3158 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3159 StringRef OptStr = Tok.getString();
3160
3161 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
3162 .Case("sy", ARM_MB::SY)
3163 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003164 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003165 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003166 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003167 .Case("ishst", ARM_MB::ISHST)
3168 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003169 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003170 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003171 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003172 .Case("osh", ARM_MB::OSH)
3173 .Case("oshst", ARM_MB::OSHST)
3174 .Default(~0U);
3175
3176 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00003177 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003178
3179 Parser.Lex(); // Eat identifier token.
3180 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00003181 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003182}
3183
Jim Grosbach43904292011-07-25 20:14:50 +00003184/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003185ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003186parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003187 SMLoc S = Parser.getTok().getLoc();
3188 const AsmToken &Tok = Parser.getTok();
3189 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3190 StringRef IFlagsStr = Tok.getString();
3191
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003192 // An iflags string of "none" is interpreted to mean that none of the AIF
3193 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003194 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003195 if (IFlagsStr != "none") {
3196 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
3197 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
3198 .Case("a", ARM_PROC::A)
3199 .Case("i", ARM_PROC::I)
3200 .Case("f", ARM_PROC::F)
3201 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003202
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003203 // If some specific iflag is already set, it means that some letter is
3204 // present more than once, this is not acceptable.
3205 if (Flag == ~0U || (IFlags & Flag))
3206 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003207
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003208 IFlags |= Flag;
3209 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003210 }
3211
3212 Parser.Lex(); // Eat identifier token.
3213 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
3214 return MatchOperand_Success;
3215}
3216
Jim Grosbach43904292011-07-25 20:14:50 +00003217/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003218ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003219parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003220 SMLoc S = Parser.getTok().getLoc();
3221 const AsmToken &Tok = Parser.getTok();
3222 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3223 StringRef Mask = Tok.getString();
3224
James Molloyacad68d2011-09-28 14:21:38 +00003225 if (isMClass()) {
3226 // See ARMv6-M 10.1.1
3227 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
3228 .Case("apsr", 0)
3229 .Case("iapsr", 1)
3230 .Case("eapsr", 2)
3231 .Case("xpsr", 3)
3232 .Case("ipsr", 5)
3233 .Case("epsr", 6)
3234 .Case("iepsr", 7)
3235 .Case("msp", 8)
3236 .Case("psp", 9)
3237 .Case("primask", 16)
3238 .Case("basepri", 17)
3239 .Case("basepri_max", 18)
3240 .Case("faultmask", 19)
3241 .Case("control", 20)
3242 .Default(~0U);
Jim Grosbach18c8d122011-12-22 17:17:10 +00003243
James Molloyacad68d2011-09-28 14:21:38 +00003244 if (FlagsVal == ~0U)
3245 return MatchOperand_NoMatch;
3246
3247 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
3248 // basepri, basepri_max and faultmask only valid for V7m.
3249 return MatchOperand_NoMatch;
Jim Grosbach18c8d122011-12-22 17:17:10 +00003250
James Molloyacad68d2011-09-28 14:21:38 +00003251 Parser.Lex(); // Eat identifier token.
3252 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3253 return MatchOperand_Success;
3254 }
3255
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003256 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
3257 size_t Start = 0, Next = Mask.find('_');
3258 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00003259 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003260 if (Next != StringRef::npos)
3261 Flags = Mask.slice(Next+1, Mask.size());
3262
3263 // FlagsVal contains the complete mask:
3264 // 3-0: Mask
3265 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3266 unsigned FlagsVal = 0;
3267
3268 if (SpecReg == "apsr") {
3269 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00003270 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003271 .Case("g", 0x4) // same as CPSR_s
3272 .Case("nzcvqg", 0xc) // same as CPSR_fs
3273 .Default(~0U);
3274
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003275 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003276 if (!Flags.empty())
3277 return MatchOperand_NoMatch;
3278 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00003279 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003280 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003281 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00003282 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
3283 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003284 for (int i = 0, e = Flags.size(); i != e; ++i) {
3285 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
3286 .Case("c", 1)
3287 .Case("x", 2)
3288 .Case("s", 4)
3289 .Case("f", 8)
3290 .Default(~0U);
3291
3292 // If some specific flag is already set, it means that some letter is
3293 // present more than once, this is not acceptable.
3294 if (FlagsVal == ~0U || (FlagsVal & Flag))
3295 return MatchOperand_NoMatch;
3296 FlagsVal |= Flag;
3297 }
3298 } else // No match for special register.
3299 return MatchOperand_NoMatch;
3300
Owen Anderson7784f1d2011-10-21 18:43:28 +00003301 // Special register without flags is NOT equivalent to "fc" flags.
3302 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3303 // two lines would enable gas compatibility at the expense of breaking
3304 // round-tripping.
3305 //
3306 // if (!FlagsVal)
3307 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003308
3309 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3310 if (SpecReg == "spsr")
3311 FlagsVal |= 16;
3312
3313 Parser.Lex(); // Eat identifier token.
3314 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3315 return MatchOperand_Success;
3316}
3317
Jim Grosbachf6c05252011-07-21 17:23:04 +00003318ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3319parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3320 int Low, int High) {
3321 const AsmToken &Tok = Parser.getTok();
3322 if (Tok.isNot(AsmToken::Identifier)) {
3323 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3324 return MatchOperand_ParseFail;
3325 }
3326 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00003327 std::string LowerOp = Op.lower();
3328 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00003329 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3330 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3331 return MatchOperand_ParseFail;
3332 }
3333 Parser.Lex(); // Eat shift type token.
3334
3335 // There must be a '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003336 if (Parser.getTok().isNot(AsmToken::Hash) &&
3337 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbachf6c05252011-07-21 17:23:04 +00003338 Error(Parser.getTok().getLoc(), "'#' expected");
3339 return MatchOperand_ParseFail;
3340 }
3341 Parser.Lex(); // Eat hash token.
3342
3343 const MCExpr *ShiftAmount;
3344 SMLoc Loc = Parser.getTok().getLoc();
3345 if (getParser().ParseExpression(ShiftAmount)) {
3346 Error(Loc, "illegal expression");
3347 return MatchOperand_ParseFail;
3348 }
3349 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3350 if (!CE) {
3351 Error(Loc, "constant expression expected");
3352 return MatchOperand_ParseFail;
3353 }
3354 int Val = CE->getValue();
3355 if (Val < Low || Val > High) {
3356 Error(Loc, "immediate value out of range");
3357 return MatchOperand_ParseFail;
3358 }
3359
3360 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3361
3362 return MatchOperand_Success;
3363}
3364
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003365ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3366parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3367 const AsmToken &Tok = Parser.getTok();
3368 SMLoc S = Tok.getLoc();
3369 if (Tok.isNot(AsmToken::Identifier)) {
3370 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3371 return MatchOperand_ParseFail;
3372 }
3373 int Val = StringSwitch<int>(Tok.getString())
3374 .Case("be", 1)
3375 .Case("le", 0)
3376 .Default(-1);
3377 Parser.Lex(); // Eat the token.
3378
3379 if (Val == -1) {
3380 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3381 return MatchOperand_ParseFail;
3382 }
3383 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3384 getContext()),
3385 S, Parser.getTok().getLoc()));
3386 return MatchOperand_Success;
3387}
3388
Jim Grosbach580f4a92011-07-25 22:20:28 +00003389/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3390/// instructions. Legal values are:
3391/// lsl #n 'n' in [0,31]
3392/// asr #n 'n' in [1,32]
3393/// n == 32 encoded as n == 0.
3394ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3395parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3396 const AsmToken &Tok = Parser.getTok();
3397 SMLoc S = Tok.getLoc();
3398 if (Tok.isNot(AsmToken::Identifier)) {
3399 Error(S, "shift operator 'asr' or 'lsl' expected");
3400 return MatchOperand_ParseFail;
3401 }
3402 StringRef ShiftName = Tok.getString();
3403 bool isASR;
3404 if (ShiftName == "lsl" || ShiftName == "LSL")
3405 isASR = false;
3406 else if (ShiftName == "asr" || ShiftName == "ASR")
3407 isASR = true;
3408 else {
3409 Error(S, "shift operator 'asr' or 'lsl' expected");
3410 return MatchOperand_ParseFail;
3411 }
3412 Parser.Lex(); // Eat the operator.
3413
3414 // A '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003415 if (Parser.getTok().isNot(AsmToken::Hash) &&
3416 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach580f4a92011-07-25 22:20:28 +00003417 Error(Parser.getTok().getLoc(), "'#' expected");
3418 return MatchOperand_ParseFail;
3419 }
3420 Parser.Lex(); // Eat hash token.
3421
3422 const MCExpr *ShiftAmount;
3423 SMLoc E = Parser.getTok().getLoc();
3424 if (getParser().ParseExpression(ShiftAmount)) {
3425 Error(E, "malformed shift expression");
3426 return MatchOperand_ParseFail;
3427 }
3428 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3429 if (!CE) {
3430 Error(E, "shift amount must be an immediate");
3431 return MatchOperand_ParseFail;
3432 }
3433
3434 int64_t Val = CE->getValue();
3435 if (isASR) {
3436 // Shift amount must be in [1,32]
3437 if (Val < 1 || Val > 32) {
3438 Error(E, "'asr' shift amount must be in range [1,32]");
3439 return MatchOperand_ParseFail;
3440 }
Owen Anderson0afa0092011-09-26 21:06:22 +00003441 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3442 if (isThumb() && Val == 32) {
3443 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3444 return MatchOperand_ParseFail;
3445 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00003446 if (Val == 32) Val = 0;
3447 } else {
3448 // Shift amount must be in [1,32]
3449 if (Val < 0 || Val > 31) {
3450 Error(E, "'lsr' shift amount must be in range [0,31]");
3451 return MatchOperand_ParseFail;
3452 }
3453 }
3454
3455 E = Parser.getTok().getLoc();
3456 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3457
3458 return MatchOperand_Success;
3459}
3460
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003461/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3462/// of instructions. Legal values are:
3463/// ror #n 'n' in {0, 8, 16, 24}
3464ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3465parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3466 const AsmToken &Tok = Parser.getTok();
3467 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00003468 if (Tok.isNot(AsmToken::Identifier))
3469 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003470 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00003471 if (ShiftName != "ror" && ShiftName != "ROR")
3472 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003473 Parser.Lex(); // Eat the operator.
3474
3475 // A '#' and a rotate amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003476 if (Parser.getTok().isNot(AsmToken::Hash) &&
3477 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003478 Error(Parser.getTok().getLoc(), "'#' expected");
3479 return MatchOperand_ParseFail;
3480 }
3481 Parser.Lex(); // Eat hash token.
3482
3483 const MCExpr *ShiftAmount;
3484 SMLoc E = Parser.getTok().getLoc();
3485 if (getParser().ParseExpression(ShiftAmount)) {
3486 Error(E, "malformed rotate expression");
3487 return MatchOperand_ParseFail;
3488 }
3489 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3490 if (!CE) {
3491 Error(E, "rotate amount must be an immediate");
3492 return MatchOperand_ParseFail;
3493 }
3494
3495 int64_t Val = CE->getValue();
3496 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3497 // normally, zero is represented in asm by omitting the rotate operand
3498 // entirely.
3499 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3500 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3501 return MatchOperand_ParseFail;
3502 }
3503
3504 E = Parser.getTok().getLoc();
3505 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3506
3507 return MatchOperand_Success;
3508}
3509
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003510ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3511parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3512 SMLoc S = Parser.getTok().getLoc();
3513 // The bitfield descriptor is really two operands, the LSB and the width.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003514 if (Parser.getTok().isNot(AsmToken::Hash) &&
3515 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003516 Error(Parser.getTok().getLoc(), "'#' expected");
3517 return MatchOperand_ParseFail;
3518 }
3519 Parser.Lex(); // Eat hash token.
3520
3521 const MCExpr *LSBExpr;
3522 SMLoc E = Parser.getTok().getLoc();
3523 if (getParser().ParseExpression(LSBExpr)) {
3524 Error(E, "malformed immediate expression");
3525 return MatchOperand_ParseFail;
3526 }
3527 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3528 if (!CE) {
3529 Error(E, "'lsb' operand must be an immediate");
3530 return MatchOperand_ParseFail;
3531 }
3532
3533 int64_t LSB = CE->getValue();
3534 // The LSB must be in the range [0,31]
3535 if (LSB < 0 || LSB > 31) {
3536 Error(E, "'lsb' operand must be in the range [0,31]");
3537 return MatchOperand_ParseFail;
3538 }
3539 E = Parser.getTok().getLoc();
3540
3541 // Expect another immediate operand.
3542 if (Parser.getTok().isNot(AsmToken::Comma)) {
3543 Error(Parser.getTok().getLoc(), "too few operands");
3544 return MatchOperand_ParseFail;
3545 }
3546 Parser.Lex(); // Eat hash token.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003547 if (Parser.getTok().isNot(AsmToken::Hash) &&
3548 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003549 Error(Parser.getTok().getLoc(), "'#' expected");
3550 return MatchOperand_ParseFail;
3551 }
3552 Parser.Lex(); // Eat hash token.
3553
3554 const MCExpr *WidthExpr;
3555 if (getParser().ParseExpression(WidthExpr)) {
3556 Error(E, "malformed immediate expression");
3557 return MatchOperand_ParseFail;
3558 }
3559 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3560 if (!CE) {
3561 Error(E, "'width' operand must be an immediate");
3562 return MatchOperand_ParseFail;
3563 }
3564
3565 int64_t Width = CE->getValue();
3566 // The LSB must be in the range [1,32-lsb]
3567 if (Width < 1 || Width > 32 - LSB) {
3568 Error(E, "'width' operand must be in the range [1,32-lsb]");
3569 return MatchOperand_ParseFail;
3570 }
3571 E = Parser.getTok().getLoc();
3572
3573 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3574
3575 return MatchOperand_Success;
3576}
3577
Jim Grosbach7ce05792011-08-03 23:50:40 +00003578ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3579parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3580 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003581 // postidx_reg := '+' register {, shift}
3582 // | '-' register {, shift}
3583 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003584
3585 // This method must return MatchOperand_NoMatch without consuming any tokens
3586 // in the case where there is no match, as other alternatives take other
3587 // parse methods.
3588 AsmToken Tok = Parser.getTok();
3589 SMLoc S = Tok.getLoc();
3590 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003591 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003592 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.
Jim Grosbach16578b52011-08-05 16:11:38 +00003598 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003599 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
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003611 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3612 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003613 if (Parser.getTok().is(AsmToken::Comma)) {
3614 Parser.Lex(); // Eat the ','.
3615 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3616 return MatchOperand_ParseFail;
3617 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003618
3619 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3620 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003621
3622 return MatchOperand_Success;
3623}
3624
Jim Grosbach251bf252011-08-10 21:56:18 +00003625ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3626parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3627 // Check for a post-index addressing register operand. Specifically:
3628 // am3offset := '+' register
3629 // | '-' register
3630 // | register
3631 // | # imm
3632 // | # + imm
3633 // | # - imm
3634
3635 // This method must return MatchOperand_NoMatch without consuming any tokens
3636 // in the case where there is no match, as other alternatives take other
3637 // parse methods.
3638 AsmToken Tok = Parser.getTok();
3639 SMLoc S = Tok.getLoc();
3640
3641 // Do immediates first, as we always parse those if we have a '#'.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003642 if (Parser.getTok().is(AsmToken::Hash) ||
3643 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach251bf252011-08-10 21:56:18 +00003644 Parser.Lex(); // Eat the '#'.
3645 // Explicitly look for a '-', as we need to encode negative zero
3646 // differently.
3647 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3648 const MCExpr *Offset;
3649 if (getParser().ParseExpression(Offset))
3650 return MatchOperand_ParseFail;
3651 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3652 if (!CE) {
3653 Error(S, "constant expression expected");
3654 return MatchOperand_ParseFail;
3655 }
3656 SMLoc E = Tok.getLoc();
3657 // Negative zero is encoded as the flag value INT32_MIN.
3658 int32_t Val = CE->getValue();
3659 if (isNegative && Val == 0)
3660 Val = INT32_MIN;
3661
3662 Operands.push_back(
3663 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3664
3665 return MatchOperand_Success;
3666 }
3667
3668
3669 bool haveEaten = false;
3670 bool isAdd = true;
3671 int Reg = -1;
3672 if (Tok.is(AsmToken::Plus)) {
3673 Parser.Lex(); // Eat the '+' token.
3674 haveEaten = true;
3675 } else if (Tok.is(AsmToken::Minus)) {
3676 Parser.Lex(); // Eat the '-' token.
3677 isAdd = false;
3678 haveEaten = true;
3679 }
3680 if (Parser.getTok().is(AsmToken::Identifier))
3681 Reg = tryParseRegister();
3682 if (Reg == -1) {
3683 if (!haveEaten)
3684 return MatchOperand_NoMatch;
3685 Error(Parser.getTok().getLoc(), "register expected");
3686 return MatchOperand_ParseFail;
3687 }
3688 SMLoc E = Parser.getTok().getLoc();
3689
3690 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3691 0, S, E));
3692
3693 return MatchOperand_Success;
3694}
3695
Jim Grosbacha77295d2011-09-08 22:07:06 +00003696/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3697/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3698/// when they refer multiple MIOperands inside a single one.
3699bool ARMAsmParser::
3700cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3701 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3702 // Rt, Rt2
3703 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3704 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3705 // Create a writeback register dummy placeholder.
3706 Inst.addOperand(MCOperand::CreateReg(0));
3707 // addr
3708 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3709 // pred
3710 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3711 return true;
3712}
3713
3714/// cvtT2StrdPre - Convert parsed operands to MCInst.
3715/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3716/// when they refer multiple MIOperands inside a single one.
3717bool ARMAsmParser::
3718cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3719 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3720 // Create a writeback register dummy placeholder.
3721 Inst.addOperand(MCOperand::CreateReg(0));
3722 // Rt, Rt2
3723 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3724 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3725 // addr
3726 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3727 // pred
3728 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3729 return true;
3730}
3731
Jim Grosbacheeec0252011-09-08 00:39:19 +00003732/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3733/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3734/// when they refer multiple MIOperands inside a single one.
3735bool ARMAsmParser::
3736cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3737 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3738 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3739
3740 // Create a writeback register dummy placeholder.
3741 Inst.addOperand(MCOperand::CreateImm(0));
3742
3743 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3744 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3745 return true;
3746}
3747
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003748/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3749/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3750/// when they refer multiple MIOperands inside a single one.
3751bool ARMAsmParser::
3752cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3753 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3754 // Create a writeback register dummy placeholder.
3755 Inst.addOperand(MCOperand::CreateImm(0));
3756 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3757 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3758 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3759 return true;
3760}
3761
Jim Grosbach1355cf12011-07-26 17:10:22 +00003762/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003763/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3764/// when they refer multiple MIOperands inside a single one.
3765bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003766cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003767 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3768 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3769
3770 // Create a writeback register dummy placeholder.
3771 Inst.addOperand(MCOperand::CreateImm(0));
3772
Jim Grosbach7ce05792011-08-03 23:50:40 +00003773 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003774 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3775 return true;
3776}
3777
Owen Anderson9ab0f252011-08-26 20:43:14 +00003778/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3779/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3780/// when they refer multiple MIOperands inside a single one.
3781bool ARMAsmParser::
3782cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3783 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3784 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3785
3786 // Create a writeback register dummy placeholder.
3787 Inst.addOperand(MCOperand::CreateImm(0));
3788
3789 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3790 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3791 return true;
3792}
3793
3794
Jim Grosbach548340c2011-08-11 19:22:40 +00003795/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3796/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3797/// when they refer multiple MIOperands inside a single one.
3798bool ARMAsmParser::
3799cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3800 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3801 // Create a writeback register dummy placeholder.
3802 Inst.addOperand(MCOperand::CreateImm(0));
3803 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3804 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3805 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3806 return true;
3807}
3808
Jim Grosbach1355cf12011-07-26 17:10:22 +00003809/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003810/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3811/// when they refer multiple MIOperands inside a single one.
3812bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003813cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003814 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3815 // Create a writeback register dummy placeholder.
3816 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003817 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3818 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3819 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003820 return true;
3821}
3822
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003823/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3824/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3825/// when they refer multiple MIOperands inside a single one.
3826bool ARMAsmParser::
3827cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3828 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3829 // Create a writeback register dummy placeholder.
3830 Inst.addOperand(MCOperand::CreateImm(0));
3831 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3832 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3833 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3834 return true;
3835}
3836
Jim Grosbach7ce05792011-08-03 23:50:40 +00003837/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3838/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3839/// when they refer multiple MIOperands inside a single one.
3840bool ARMAsmParser::
3841cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3842 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3843 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003844 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003845 // Create a writeback register dummy placeholder.
3846 Inst.addOperand(MCOperand::CreateImm(0));
3847 // addr
3848 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3849 // offset
3850 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3851 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003852 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3853 return true;
3854}
3855
Jim Grosbach7ce05792011-08-03 23:50:40 +00003856/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003857/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3858/// when they refer multiple MIOperands inside a single one.
3859bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003860cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3861 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3862 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003863 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003864 // Create a writeback register dummy placeholder.
3865 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003866 // addr
3867 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3868 // offset
3869 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3870 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003871 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3872 return true;
3873}
3874
Jim Grosbach7ce05792011-08-03 23:50:40 +00003875/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003876/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3877/// when they refer multiple MIOperands inside a single one.
3878bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003879cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3880 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003881 // Create a writeback register dummy placeholder.
3882 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003883 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003884 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003885 // addr
3886 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3887 // offset
3888 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3889 // pred
3890 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3891 return true;
3892}
3893
3894/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3895/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3896/// when they refer multiple MIOperands inside a single one.
3897bool ARMAsmParser::
3898cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3899 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3900 // Create a writeback register dummy placeholder.
3901 Inst.addOperand(MCOperand::CreateImm(0));
3902 // Rt
3903 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3904 // addr
3905 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3906 // offset
3907 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3908 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003909 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3910 return true;
3911}
3912
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003913/// cvtLdrdPre - Convert parsed operands to MCInst.
3914/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3915/// when they refer multiple MIOperands inside a single one.
3916bool ARMAsmParser::
3917cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3918 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3919 // Rt, Rt2
3920 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3921 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3922 // Create a writeback register dummy placeholder.
3923 Inst.addOperand(MCOperand::CreateImm(0));
3924 // addr
3925 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3926 // pred
3927 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3928 return true;
3929}
3930
Jim Grosbach14605d12011-08-11 20:28:23 +00003931/// cvtStrdPre - Convert parsed operands to MCInst.
3932/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3933/// when they refer multiple MIOperands inside a single one.
3934bool ARMAsmParser::
3935cvtStrdPre(MCInst &Inst, unsigned Opcode,
3936 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3937 // Create a writeback register dummy placeholder.
3938 Inst.addOperand(MCOperand::CreateImm(0));
3939 // Rt, Rt2
3940 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3941 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3942 // addr
3943 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3944 // pred
3945 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3946 return true;
3947}
3948
Jim Grosbach623a4542011-08-10 22:42:16 +00003949/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3950/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3951/// when they refer multiple MIOperands inside a single one.
3952bool ARMAsmParser::
3953cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3954 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3955 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3956 // Create a writeback register dummy placeholder.
3957 Inst.addOperand(MCOperand::CreateImm(0));
3958 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3959 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3960 return true;
3961}
3962
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003963/// cvtThumbMultiple- Convert parsed operands to MCInst.
3964/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3965/// when they refer multiple MIOperands inside a single one.
3966bool ARMAsmParser::
3967cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3968 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3969 // The second source operand must be the same register as the destination
3970 // operand.
3971 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003972 (((ARMOperand*)Operands[3])->getReg() !=
3973 ((ARMOperand*)Operands[5])->getReg()) &&
3974 (((ARMOperand*)Operands[3])->getReg() !=
3975 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003976 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003977 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003978 return false;
3979 }
3980 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3981 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach1b332862011-11-10 22:10:12 +00003982 // If we have a three-operand form, make sure to set Rn to be the operand
3983 // that isn't the same as Rd.
3984 unsigned RegOp = 4;
3985 if (Operands.size() == 6 &&
3986 ((ARMOperand*)Operands[4])->getReg() ==
3987 ((ARMOperand*)Operands[3])->getReg())
3988 RegOp = 5;
3989 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
3990 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003991 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3992
3993 return true;
3994}
Jim Grosbach623a4542011-08-10 22:42:16 +00003995
Jim Grosbach12431322011-10-24 22:16:58 +00003996bool ARMAsmParser::
3997cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3998 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3999 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004000 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00004001 // Create a writeback register dummy placeholder.
4002 Inst.addOperand(MCOperand::CreateImm(0));
4003 // Vn
4004 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4005 // pred
4006 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4007 return true;
4008}
4009
4010bool ARMAsmParser::
4011cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
4012 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4013 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004014 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00004015 // Create a writeback register dummy placeholder.
4016 Inst.addOperand(MCOperand::CreateImm(0));
4017 // Vn
4018 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4019 // Vm
4020 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4021 // pred
4022 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4023 return true;
4024}
4025
Jim Grosbach4334e032011-10-31 21:50:31 +00004026bool ARMAsmParser::
4027cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
4028 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4029 // Create a writeback register dummy placeholder.
4030 Inst.addOperand(MCOperand::CreateImm(0));
4031 // Vn
4032 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4033 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004034 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00004035 // pred
4036 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4037 return true;
4038}
4039
4040bool ARMAsmParser::
4041cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
4042 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4043 // Create a writeback register dummy placeholder.
4044 Inst.addOperand(MCOperand::CreateImm(0));
4045 // Vn
4046 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4047 // Vm
4048 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4049 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004050 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00004051 // pred
4052 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4053 return true;
4054}
4055
Bill Wendlinge7176102010-11-06 22:36:58 +00004056/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004057/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00004058bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00004059parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00004060 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00004061 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00004062 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00004063 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004064 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004065
Sean Callanan18b83232010-01-19 21:44:56 +00004066 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00004067 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00004068 if (BaseRegNum == -1)
4069 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004070
Daniel Dunbar05710932011-01-18 05:34:17 +00004071 // The next token must either be a comma or a closing bracket.
4072 const AsmToken &Tok = Parser.getTok();
4073 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004074 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00004075
Jim Grosbach7ce05792011-08-03 23:50:40 +00004076 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00004077 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004078 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004079
Jim Grosbach7ce05792011-08-03 23:50:40 +00004080 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004081 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00004082
Jim Grosbachfb12f352011-09-19 18:42:21 +00004083 // If there's a pre-indexing writeback marker, '!', just add it as a token
4084 // operand. It's rather odd, but syntactically valid.
4085 if (Parser.getTok().is(AsmToken::Exclaim)) {
4086 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4087 Parser.Lex(); // Eat the '!'.
4088 }
4089
Jim Grosbach7ce05792011-08-03 23:50:40 +00004090 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004091 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004092
Jim Grosbach7ce05792011-08-03 23:50:40 +00004093 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
4094 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004095
Jim Grosbach57dcb852011-10-11 17:29:55 +00004096 // If we have a ':', it's an alignment specifier.
4097 if (Parser.getTok().is(AsmToken::Colon)) {
4098 Parser.Lex(); // Eat the ':'.
4099 E = Parser.getTok().getLoc();
4100
4101 const MCExpr *Expr;
4102 if (getParser().ParseExpression(Expr))
4103 return true;
4104
4105 // The expression has to be a constant. Memory references with relocations
4106 // don't come through here, as they use the <label> forms of the relevant
4107 // instructions.
4108 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4109 if (!CE)
4110 return Error (E, "constant expression expected");
4111
4112 unsigned Align = 0;
4113 switch (CE->getValue()) {
4114 default:
Jim Grosbacheeaf1c12011-12-19 18:31:43 +00004115 return Error(E,
4116 "alignment specifier must be 16, 32, 64, 128, or 256 bits");
4117 case 16: Align = 2; break;
4118 case 32: Align = 4; break;
Jim Grosbach57dcb852011-10-11 17:29:55 +00004119 case 64: Align = 8; break;
4120 case 128: Align = 16; break;
4121 case 256: Align = 32; break;
4122 }
4123
4124 // Now we should have the closing ']'
4125 E = Parser.getTok().getLoc();
4126 if (Parser.getTok().isNot(AsmToken::RBrac))
4127 return Error(E, "']' expected");
4128 Parser.Lex(); // Eat right bracket token.
4129
4130 // Don't worry about range checking the value here. That's handled by
4131 // the is*() predicates.
4132 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
4133 ARM_AM::no_shift, 0, Align,
4134 false, S, E));
4135
4136 // If there's a pre-indexing writeback marker, '!', just add it as a token
4137 // operand.
4138 if (Parser.getTok().is(AsmToken::Exclaim)) {
4139 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4140 Parser.Lex(); // Eat the '!'.
4141 }
4142
4143 return false;
4144 }
4145
4146 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004147 // offset. Be friendly and also accept a plain integer (without a leading
4148 // hash) for gas compatibility.
4149 if (Parser.getTok().is(AsmToken::Hash) ||
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004150 Parser.getTok().is(AsmToken::Dollar) ||
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004151 Parser.getTok().is(AsmToken::Integer)) {
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004152 if (Parser.getTok().isNot(AsmToken::Integer))
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004153 Parser.Lex(); // Eat the '#'.
Jim Grosbach7ce05792011-08-03 23:50:40 +00004154 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004155
Owen Anderson0da10cf2011-08-29 19:36:44 +00004156 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00004157 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004158 if (getParser().ParseExpression(Offset))
4159 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004160
4161 // The expression has to be a constant. Memory references with relocations
4162 // don't come through here, as they use the <label> forms of the relevant
4163 // instructions.
4164 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
4165 if (!CE)
4166 return Error (E, "constant expression expected");
4167
Owen Anderson0da10cf2011-08-29 19:36:44 +00004168 // If the constant was #-0, represent it as INT32_MIN.
4169 int32_t Val = CE->getValue();
4170 if (isNegative && Val == 0)
4171 CE = MCConstantExpr::Create(INT32_MIN, getContext());
4172
Jim Grosbach7ce05792011-08-03 23:50:40 +00004173 // Now we should have the closing ']'
4174 E = Parser.getTok().getLoc();
4175 if (Parser.getTok().isNot(AsmToken::RBrac))
4176 return Error(E, "']' expected");
4177 Parser.Lex(); // Eat right bracket token.
4178
4179 // Don't worry about range checking the value here. That's handled by
4180 // the is*() predicates.
4181 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004182 ARM_AM::no_shift, 0, 0,
4183 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00004184
4185 // If there's a pre-indexing writeback marker, '!', just add it as a token
4186 // operand.
4187 if (Parser.getTok().is(AsmToken::Exclaim)) {
4188 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4189 Parser.Lex(); // Eat the '!'.
4190 }
4191
4192 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004193 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004194
4195 // The register offset is optionally preceded by a '+' or '-'
4196 bool isNegative = false;
4197 if (Parser.getTok().is(AsmToken::Minus)) {
4198 isNegative = true;
4199 Parser.Lex(); // Eat the '-'.
4200 } else if (Parser.getTok().is(AsmToken::Plus)) {
4201 // Nothing to do.
4202 Parser.Lex(); // Eat the '+'.
4203 }
4204
4205 E = Parser.getTok().getLoc();
4206 int OffsetRegNum = tryParseRegister();
4207 if (OffsetRegNum == -1)
4208 return Error(E, "register expected");
4209
4210 // If there's a shift operator, handle it.
4211 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004212 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004213 if (Parser.getTok().is(AsmToken::Comma)) {
4214 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004215 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004216 return true;
4217 }
4218
4219 // Now we should have the closing ']'
4220 E = Parser.getTok().getLoc();
4221 if (Parser.getTok().isNot(AsmToken::RBrac))
4222 return Error(E, "']' expected");
4223 Parser.Lex(); // Eat right bracket token.
4224
4225 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004226 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00004227 S, E));
4228
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00004229 // If there's a pre-indexing writeback marker, '!', just add it as a token
4230 // operand.
4231 if (Parser.getTok().is(AsmToken::Exclaim)) {
4232 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4233 Parser.Lex(); // Eat the '!'.
4234 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004235
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004236 return false;
4237}
4238
Jim Grosbach7ce05792011-08-03 23:50:40 +00004239/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004240/// ( lsl | lsr | asr | ror ) , # shift_amount
4241/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00004242/// return true if it parses a shift otherwise it returns false.
4243bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
4244 unsigned &Amount) {
4245 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00004246 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004247 if (Tok.isNot(AsmToken::Identifier))
4248 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00004249 StringRef ShiftName = Tok.getString();
Jim Grosbachaf4edea2011-12-07 23:40:58 +00004250 if (ShiftName == "lsl" || ShiftName == "LSL" ||
4251 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson00828302011-03-18 22:50:18 +00004252 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004253 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00004254 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004255 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00004256 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004257 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00004258 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004259 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00004260 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004261 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00004262 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00004263 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004264
Jim Grosbach7ce05792011-08-03 23:50:40 +00004265 // rrx stands alone.
4266 Amount = 0;
4267 if (St != ARM_AM::rrx) {
4268 Loc = Parser.getTok().getLoc();
4269 // A '#' and a shift amount.
4270 const AsmToken &HashTok = Parser.getTok();
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004271 if (HashTok.isNot(AsmToken::Hash) &&
4272 HashTok.isNot(AsmToken::Dollar))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004273 return Error(HashTok.getLoc(), "'#' expected");
4274 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004275
Jim Grosbach7ce05792011-08-03 23:50:40 +00004276 const MCExpr *Expr;
4277 if (getParser().ParseExpression(Expr))
4278 return true;
4279 // Range check the immediate.
4280 // lsl, ror: 0 <= imm <= 31
4281 // lsr, asr: 0 <= imm <= 32
4282 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4283 if (!CE)
4284 return Error(Loc, "shift amount must be an immediate");
4285 int64_t Imm = CE->getValue();
4286 if (Imm < 0 ||
4287 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4288 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4289 return Error(Loc, "immediate shift value out of range");
4290 Amount = Imm;
4291 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004292
4293 return false;
4294}
4295
Jim Grosbach9d390362011-10-03 23:38:36 +00004296/// parseFPImm - A floating point immediate expression operand.
4297ARMAsmParser::OperandMatchResultTy ARMAsmParser::
4298parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach51222d12012-01-20 18:09:51 +00004299 // Anything that can accept a floating point constant as an operand
4300 // needs to go through here, as the regular ParseExpression is
4301 // integer only.
4302 //
4303 // This routine still creates a generic Immediate operand, containing
4304 // a bitcast of the 64-bit floating point value. The various operands
4305 // that accept floats can check whether the value is valid for them
4306 // via the standard is*() predicates.
4307
Jim Grosbach9d390362011-10-03 23:38:36 +00004308 SMLoc S = Parser.getTok().getLoc();
4309
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004310 if (Parser.getTok().isNot(AsmToken::Hash) &&
4311 Parser.getTok().isNot(AsmToken::Dollar))
Jim Grosbach9d390362011-10-03 23:38:36 +00004312 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00004313
4314 // Disambiguate the VMOV forms that can accept an FP immediate.
4315 // vmov.f32 <sreg>, #imm
4316 // vmov.f64 <dreg>, #imm
4317 // vmov.f32 <dreg>, #imm @ vector f32x2
4318 // vmov.f32 <qreg>, #imm @ vector f32x4
4319 //
4320 // There are also the NEON VMOV instructions which expect an
4321 // integer constant. Make sure we don't try to parse an FPImm
4322 // for these:
4323 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4324 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4325 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4326 TyOp->getToken() != ".f64"))
4327 return MatchOperand_NoMatch;
4328
Jim Grosbach9d390362011-10-03 23:38:36 +00004329 Parser.Lex(); // Eat the '#'.
4330
4331 // Handle negation, as that still comes through as a separate token.
4332 bool isNegative = false;
4333 if (Parser.getTok().is(AsmToken::Minus)) {
4334 isNegative = true;
4335 Parser.Lex();
4336 }
4337 const AsmToken &Tok = Parser.getTok();
Jim Grosbachae69f702012-01-19 02:47:30 +00004338 SMLoc Loc = Tok.getLoc();
Jim Grosbach9d390362011-10-03 23:38:36 +00004339 if (Tok.is(AsmToken::Real)) {
Jim Grosbach51222d12012-01-20 18:09:51 +00004340 APFloat RealVal(APFloat::IEEEsingle, Tok.getString());
Jim Grosbach9d390362011-10-03 23:38:36 +00004341 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4342 // If we had a '-' in front, toggle the sign bit.
Jim Grosbach51222d12012-01-20 18:09:51 +00004343 IntVal ^= (uint64_t)isNegative << 31;
Jim Grosbach9d390362011-10-03 23:38:36 +00004344 Parser.Lex(); // Eat the token.
Jim Grosbach51222d12012-01-20 18:09:51 +00004345 Operands.push_back(ARMOperand::CreateImm(
4346 MCConstantExpr::Create(IntVal, getContext()),
4347 S, Parser.getTok().getLoc()));
Jim Grosbach9d390362011-10-03 23:38:36 +00004348 return MatchOperand_Success;
4349 }
Jim Grosbach51222d12012-01-20 18:09:51 +00004350 // Also handle plain integers. Instructions which allow floating point
4351 // immediates also allow a raw encoded 8-bit value.
Jim Grosbach9d390362011-10-03 23:38:36 +00004352 if (Tok.is(AsmToken::Integer)) {
4353 int64_t Val = Tok.getIntVal();
4354 Parser.Lex(); // Eat the token.
4355 if (Val > 255 || Val < 0) {
Jim Grosbachae69f702012-01-19 02:47:30 +00004356 Error(Loc, "encoded floating point value out of range");
Jim Grosbach9d390362011-10-03 23:38:36 +00004357 return MatchOperand_ParseFail;
4358 }
Jim Grosbach51222d12012-01-20 18:09:51 +00004359 double RealVal = ARM_AM::getFPImmFloat(Val);
4360 Val = APFloat(APFloat::IEEEdouble, RealVal).bitcastToAPInt().getZExtValue();
4361 Operands.push_back(ARMOperand::CreateImm(
4362 MCConstantExpr::Create(Val, getContext()), S,
4363 Parser.getTok().getLoc()));
Jim Grosbach9d390362011-10-03 23:38:36 +00004364 return MatchOperand_Success;
4365 }
4366
Jim Grosbachae69f702012-01-19 02:47:30 +00004367 Error(Loc, "invalid floating point immediate");
Jim Grosbach9d390362011-10-03 23:38:36 +00004368 return MatchOperand_ParseFail;
4369}
Jim Grosbach51222d12012-01-20 18:09:51 +00004370
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004371/// Parse a arm instruction operand. For now this parses the operand regardless
4372/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004373bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004374 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00004375 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004376
4377 // Check if the current operand has a custom associated parser, if so, try to
4378 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00004379 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4380 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004381 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00004382 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4383 // there was a match, but an error occurred, in which case, just return that
4384 // the operand parsing failed.
4385 if (ResTy == MatchOperand_ParseFail)
4386 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004387
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004388 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00004389 default:
4390 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00004391 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00004392 case AsmToken::Identifier: {
Jim Grosbach1355cf12011-07-26 17:10:22 +00004393 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00004394 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00004395 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00004396 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00004397 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00004398 else if (Res == -1) // irrecoverable error
4399 return true;
Jim Grosbach3cbe43f2011-12-20 22:26:38 +00004400 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004401 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
4402 S = Parser.getTok().getLoc();
4403 Parser.Lex();
4404 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
4405 return false;
4406 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00004407
4408 // Fall though for the Identifier case that is not a register or a
4409 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00004410 }
Jim Grosbach758a5192011-10-26 21:14:08 +00004411 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00004412 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00004413 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00004414 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00004415 // This was not a register so parse other operands that start with an
4416 // identifier (like labels) as expressions and create them as immediates.
4417 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00004418 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00004419 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004420 return true;
Sean Callanan76264762010-04-02 22:27:05 +00004421 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004422 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4423 return false;
4424 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004425 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004426 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00004427 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004428 return parseRegisterList(Operands);
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004429 case AsmToken::Dollar:
Owen Anderson63553c72011-08-29 17:17:09 +00004430 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00004431 // #42 -> immediate.
4432 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00004433 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004434 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00004435 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00004436 const MCExpr *ImmVal;
4437 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004438 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00004439 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbached6a0c52011-11-01 22:37:37 +00004440 if (CE) {
4441 int32_t Val = CE->getValue();
4442 if (isNegative && Val == 0)
4443 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Anderson63553c72011-08-29 17:17:09 +00004444 }
Sean Callanan76264762010-04-02 22:27:05 +00004445 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004446 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4447 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00004448 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004449 case AsmToken::Colon: {
4450 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00004451 // FIXME: Check it's an expression prefix,
4452 // e.g. (FOO - :lower16:BAR) isn't legal.
4453 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004454 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004455 return true;
4456
Evan Cheng75972122011-01-13 07:58:56 +00004457 const MCExpr *SubExprVal;
4458 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004459 return true;
4460
Evan Cheng75972122011-01-13 07:58:56 +00004461 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4462 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00004463 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00004464 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00004465 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004466 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004467 }
4468}
4469
Jim Grosbach1355cf12011-07-26 17:10:22 +00004470// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00004471// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004472bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00004473 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004474
4475 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00004476 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00004477 Parser.Lex(); // Eat ':'
4478
4479 if (getLexer().isNot(AsmToken::Identifier)) {
4480 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4481 return true;
4482 }
4483
4484 StringRef IDVal = Parser.getTok().getIdentifier();
4485 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00004486 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004487 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00004488 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004489 } else {
4490 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4491 return true;
4492 }
4493 Parser.Lex();
4494
4495 if (getLexer().isNot(AsmToken::Colon)) {
4496 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4497 return true;
4498 }
4499 Parser.Lex(); // Eat the last ':'
4500 return false;
4501}
4502
Daniel Dunbar352e1482011-01-11 15:59:50 +00004503/// \brief Given a mnemonic, split out possible predication code and carry
4504/// setting letters to form a canonical mnemonic and flags.
4505//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004506// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00004507// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004508StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00004509 unsigned &PredicationCode,
4510 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004511 unsigned &ProcessorIMod,
4512 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004513 PredicationCode = ARMCC::AL;
4514 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004515 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004516
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004517 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00004518 //
4519 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00004520 if ((Mnemonic == "movs" && isThumb()) ||
4521 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4522 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4523 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4524 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4525 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4526 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
Jim Grosbach68490192011-12-19 19:43:50 +00004527 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" ||
4528 Mnemonic == "fmuls")
Daniel Dunbar352e1482011-01-11 15:59:50 +00004529 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00004530
Jim Grosbach3f00e312011-07-11 17:09:57 +00004531 // First, split out any predication code. Ignore mnemonics we know aren't
4532 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00004533 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00004534 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00004535 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00004536 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00004537 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4538 .Case("eq", ARMCC::EQ)
4539 .Case("ne", ARMCC::NE)
4540 .Case("hs", ARMCC::HS)
4541 .Case("cs", ARMCC::HS)
4542 .Case("lo", ARMCC::LO)
4543 .Case("cc", ARMCC::LO)
4544 .Case("mi", ARMCC::MI)
4545 .Case("pl", ARMCC::PL)
4546 .Case("vs", ARMCC::VS)
4547 .Case("vc", ARMCC::VC)
4548 .Case("hi", ARMCC::HI)
4549 .Case("ls", ARMCC::LS)
4550 .Case("ge", ARMCC::GE)
4551 .Case("lt", ARMCC::LT)
4552 .Case("gt", ARMCC::GT)
4553 .Case("le", ARMCC::LE)
4554 .Case("al", ARMCC::AL)
4555 .Default(~0U);
4556 if (CC != ~0U) {
4557 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4558 PredicationCode = CC;
4559 }
Bill Wendling52925b62010-10-29 23:50:21 +00004560 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004561
Daniel Dunbar352e1482011-01-11 15:59:50 +00004562 // Next, determine if we have a carry setting bit. We explicitly ignore all
4563 // the instructions we know end in 's'.
4564 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00004565 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00004566 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4567 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4568 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach67ca1ad2011-12-08 00:49:29 +00004569 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach48171e72011-12-10 00:01:02 +00004570 Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
Jim Grosbach9c397892011-12-19 19:02:41 +00004571 Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" ||
Jim Grosbach1aa149f2011-12-22 19:20:45 +00004572 Mnemonic == "fmuls" || Mnemonic == "fcmps" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00004573 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004574 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4575 CarrySetting = true;
4576 }
4577
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004578 // The "cps" instruction can have a interrupt mode operand which is glued into
4579 // the mnemonic. Check if this is the case, split it and parse the imod op
4580 if (Mnemonic.startswith("cps")) {
4581 // Split out any imod code.
4582 unsigned IMod =
4583 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4584 .Case("ie", ARM_PROC::IE)
4585 .Case("id", ARM_PROC::ID)
4586 .Default(~0U);
4587 if (IMod != ~0U) {
4588 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4589 ProcessorIMod = IMod;
4590 }
4591 }
4592
Jim Grosbach89df9962011-08-26 21:43:41 +00004593 // The "it" instruction has the condition mask on the end of the mnemonic.
4594 if (Mnemonic.startswith("it")) {
4595 ITMask = Mnemonic.slice(2, Mnemonic.size());
4596 Mnemonic = Mnemonic.slice(0, 2);
4597 }
4598
Daniel Dunbar352e1482011-01-11 15:59:50 +00004599 return Mnemonic;
4600}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004601
4602/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4603/// inclusion of carry set or predication code operands.
4604//
4605// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004606void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00004607getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004608 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004609 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4610 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004611 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004612 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004613 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004614 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004615 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004616 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004617 Mnemonic == "mla" || Mnemonic == "smlal" ||
4618 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004619 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004620 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004621 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004622
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004623 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4624 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4625 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4626 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004627 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4628 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004629 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004630 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4631 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4632 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004633 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4634 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004635 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004636 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004637 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004638 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004639
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004640 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004641 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004642 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004643 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004644 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004645}
4646
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004647bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4648 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004649 // FIXME: This is all horribly hacky. We really need a better way to deal
4650 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004651
4652 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4653 // another does not. Specifically, the MOVW instruction does not. So we
4654 // special case it here and remove the defaulted (non-setting) cc_out
4655 // operand if that's the instruction we're trying to match.
4656 //
4657 // We do this as post-processing of the explicit operands rather than just
4658 // conditionally adding the cc_out in the first place because we need
4659 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004660 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004661 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4662 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4663 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4664 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004665
4666 // Register-register 'add' for thumb does not have a cc_out operand
4667 // when there are only two register operands.
4668 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4669 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4670 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4671 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4672 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004673 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004674 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4675 // have to check the immediate range here since Thumb2 has a variant
4676 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004677 if (((isThumb() && Mnemonic == "add") ||
4678 (isThumbTwo() && Mnemonic == "sub")) &&
4679 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004680 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4681 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4682 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004683 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4684 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4685 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004686 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004687 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4688 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004689 // selecting via the generic "add" mnemonic, so to know that we
4690 // should remove the cc_out operand, we have to explicitly check that
4691 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004692 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4693 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004694 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4695 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4696 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4697 // Nest conditions rather than one big 'if' statement for readability.
4698 //
4699 // If either register is a high reg, it's either one of the SP
4700 // variants (handled above) or a 32-bit encoding, so we just
Jim Grosbach12a88632012-01-21 00:07:56 +00004701 // check against T3. If the second register is the PC, this is an
4702 // alternate form of ADR, which uses encoding T4, so check for that too.
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004703 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4704 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
Jim Grosbach12a88632012-01-21 00:07:56 +00004705 static_cast<ARMOperand*>(Operands[4])->getReg() != ARM::PC &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004706 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4707 return false;
4708 // If both registers are low, we're in an IT block, and the immediate is
4709 // in range, we should use encoding T1 instead, which has a cc_out.
4710 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004711 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004712 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4713 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4714 return false;
4715
4716 // Otherwise, we use encoding T4, which does not have a cc_out
4717 // operand.
4718 return true;
4719 }
4720
Jim Grosbach64944f42011-09-14 21:00:40 +00004721 // The thumb2 multiply instruction doesn't have a CCOut register, so
4722 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4723 // use the 16-bit encoding or not.
4724 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4725 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4726 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4727 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4728 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4729 // If the registers aren't low regs, the destination reg isn't the
4730 // same as one of the source regs, or the cc_out operand is zero
4731 // outside of an IT block, we have to use the 32-bit encoding, so
4732 // remove the cc_out operand.
4733 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4734 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach1de0bd12011-11-15 19:29:45 +00004735 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach64944f42011-09-14 21:00:40 +00004736 !inITBlock() ||
4737 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4738 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4739 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4740 static_cast<ARMOperand*>(Operands[4])->getReg())))
4741 return true;
4742
Jim Grosbach7f1ec952011-11-15 19:55:16 +00004743 // Also check the 'mul' syntax variant that doesn't specify an explicit
4744 // destination register.
4745 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4746 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4747 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4748 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4749 // If the registers aren't low regs or the cc_out operand is zero
4750 // outside of an IT block, we have to use the 32-bit encoding, so
4751 // remove the cc_out operand.
4752 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4753 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4754 !inITBlock()))
4755 return true;
4756
Jim Grosbach64944f42011-09-14 21:00:40 +00004757
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004758
Jim Grosbachf69c8042011-08-24 21:42:27 +00004759 // Register-register 'add/sub' for thumb does not have a cc_out operand
4760 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4761 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4762 // right, this will result in better diagnostics (which operand is off)
4763 // anyway.
4764 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4765 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004766 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4767 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4768 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4769 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004770
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004771 return false;
4772}
4773
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004774static bool isDataTypeToken(StringRef Tok) {
4775 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4776 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4777 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4778 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4779 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4780 Tok == ".f" || Tok == ".d";
4781}
4782
4783// FIXME: This bit should probably be handled via an explicit match class
4784// in the .td files that matches the suffix instead of having it be
4785// a literal string token the way it is now.
4786static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4787 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4788}
4789
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004790static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004791/// Parse an arm instruction mnemonic followed by its operands.
4792bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4793 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004794 // Apply mnemonic aliases before doing anything else, as the destination
4795 // mnemnonic may include suffices and we want to handle them normally.
4796 // The generic tblgen'erated code does this later, at the start of
4797 // MatchInstructionImpl(), but that's too late for aliases that include
4798 // any sort of suffix.
4799 unsigned AvailableFeatures = getAvailableFeatures();
4800 applyMnemonicAliases(Name, AvailableFeatures);
4801
Jim Grosbacha39cda72011-12-14 02:16:11 +00004802 // First check for the ARM-specific .req directive.
4803 if (Parser.getTok().is(AsmToken::Identifier) &&
4804 Parser.getTok().getIdentifier() == ".req") {
4805 parseDirectiveReq(Name, NameLoc);
4806 // We always return 'error' for this, as we're done with this
4807 // statement and don't need to match the 'instruction."
4808 return true;
4809 }
4810
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004811 // Create the leading tokens for the mnemonic, split by '.' characters.
4812 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004813 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004814
Daniel Dunbar352e1482011-01-11 15:59:50 +00004815 // Split out the predication code and carry setting flag from the mnemonic.
4816 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004817 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004818 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004819 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004820 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004821 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004822
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004823 // In Thumb1, only the branch (B) instruction can be predicated.
4824 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4825 Parser.EatToEndOfStatement();
4826 return Error(NameLoc, "conditional execution not supported in Thumb1");
4827 }
4828
Jim Grosbachffa32252011-07-19 19:13:28 +00004829 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4830
Jim Grosbach89df9962011-08-26 21:43:41 +00004831 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4832 // is the mask as it will be for the IT encoding if the conditional
4833 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4834 // where the conditional bit0 is zero, the instruction post-processing
4835 // will adjust the mask accordingly.
4836 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004837 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4838 if (ITMask.size() > 3) {
4839 Parser.EatToEndOfStatement();
4840 return Error(Loc, "too many conditions on IT instruction");
4841 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004842 unsigned Mask = 8;
4843 for (unsigned i = ITMask.size(); i != 0; --i) {
4844 char pos = ITMask[i - 1];
4845 if (pos != 't' && pos != 'e') {
4846 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004847 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004848 }
4849 Mask >>= 1;
4850 if (ITMask[i - 1] == 't')
4851 Mask |= 8;
4852 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004853 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004854 }
4855
Jim Grosbachffa32252011-07-19 19:13:28 +00004856 // FIXME: This is all a pretty gross hack. We should automatically handle
4857 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004858
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004859 // Next, add the CCOut and ConditionCode operands, if needed.
4860 //
4861 // For mnemonics which can ever incorporate a carry setting bit or predication
4862 // code, our matching model involves us always generating CCOut and
4863 // ConditionCode operands to match the mnemonic "as written" and then we let
4864 // the matcher deal with finding the right instruction or generating an
4865 // appropriate error.
4866 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004867 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004868
Jim Grosbach33c16a22011-07-14 22:04:21 +00004869 // If we had a carry-set on an instruction that can't do that, issue an
4870 // error.
4871 if (!CanAcceptCarrySet && CarrySetting) {
4872 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004873 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004874 "' can not set flags, but 's' suffix specified");
4875 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004876 // If we had a predication code on an instruction that can't do that, issue an
4877 // error.
4878 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4879 Parser.EatToEndOfStatement();
4880 return Error(NameLoc, "instruction '" + Mnemonic +
4881 "' is not predicable, but condition code specified");
4882 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004883
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004884 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004885 if (CanAcceptCarrySet) {
4886 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004887 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004888 Loc));
4889 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004890
4891 // Add the predication code operand, if necessary.
4892 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004893 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4894 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004895 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004896 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004897 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004898
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004899 // Add the processor imod operand, if necessary.
4900 if (ProcessorIMod) {
4901 Operands.push_back(ARMOperand::CreateImm(
4902 MCConstantExpr::Create(ProcessorIMod, getContext()),
4903 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004904 }
4905
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004906 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004907 while (Next != StringRef::npos) {
4908 Start = Next;
4909 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004910 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004911
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004912 // Some NEON instructions have an optional datatype suffix that is
4913 // completely ignored. Check for that.
4914 if (isDataTypeToken(ExtraToken) &&
4915 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4916 continue;
4917
Jim Grosbach81d2e392011-09-07 16:06:04 +00004918 if (ExtraToken != ".n") {
4919 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4920 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4921 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004922 }
4923
4924 // Read the remaining operands.
4925 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004926 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004927 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004928 Parser.EatToEndOfStatement();
4929 return true;
4930 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004931
4932 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004933 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004934
4935 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004936 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004937 Parser.EatToEndOfStatement();
4938 return true;
4939 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004940 }
4941 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004942
Chris Lattnercbf8a982010-09-11 16:18:25 +00004943 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004944 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004945 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004946 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004947 }
Bill Wendling146018f2010-11-06 21:42:12 +00004948
Chris Lattner34e53142010-09-08 05:10:46 +00004949 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004950
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004951 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4952 // do and don't have a cc_out optional-def operand. With some spot-checks
4953 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004954 // parse and adjust accordingly before actually matching. We shouldn't ever
4955 // try to remove a cc_out operand that was explicitly set on the the
4956 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4957 // table driven matcher doesn't fit well with the ARM instruction set.
4958 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004959 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4960 Operands.erase(Operands.begin() + 1);
4961 delete Op;
4962 }
4963
Jim Grosbachcf121c32011-07-28 21:57:55 +00004964 // ARM mode 'blx' need special handling, as the register operand version
4965 // is predicable, but the label operand version is not. So, we can't rely
4966 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004967 // a k_CondCode operand in the list. If we're trying to match the label
4968 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004969 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4970 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4971 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4972 Operands.erase(Operands.begin() + 1);
4973 delete Op;
4974 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00004975
4976 // The vector-compare-to-zero instructions have a literal token "#0" at
4977 // the end that comes to here as an immediate operand. Convert it to a
4978 // token to play nicely with the matcher.
4979 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4980 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4981 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4982 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4983 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4984 if (CE && CE->getValue() == 0) {
4985 Operands.erase(Operands.begin() + 5);
4986 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4987 delete Op;
4988 }
4989 }
Jim Grosbach68259142011-10-03 22:30:24 +00004990 // VCMP{E} does the same thing, but with a different operand count.
4991 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4992 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4993 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4994 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4995 if (CE && CE->getValue() == 0) {
4996 Operands.erase(Operands.begin() + 4);
4997 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4998 delete Op;
4999 }
5000 }
Jim Grosbach934755a2011-08-22 23:47:13 +00005001 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
Jim Grosbach55b02f22011-12-13 20:50:38 +00005002 // end. Convert it to a token here. Take care not to convert those
5003 // that should hit the Thumb2 encoding.
Jim Grosbach934755a2011-08-22 23:47:13 +00005004 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
Jim Grosbach55b02f22011-12-13 20:50:38 +00005005 static_cast<ARMOperand*>(Operands[3])->isReg() &&
5006 static_cast<ARMOperand*>(Operands[4])->isReg() &&
Jim Grosbach934755a2011-08-22 23:47:13 +00005007 static_cast<ARMOperand*>(Operands[5])->isImm()) {
5008 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
5009 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
Jim Grosbach55b02f22011-12-13 20:50:38 +00005010 if (CE && CE->getValue() == 0 &&
5011 (isThumbOne() ||
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00005012 // The cc_out operand matches the IT block.
5013 ((inITBlock() != CarrySetting) &&
5014 // Neither register operand is a high register.
Jim Grosbach55b02f22011-12-13 20:50:38 +00005015 (isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00005016 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()))))){
Jim Grosbach934755a2011-08-22 23:47:13 +00005017 Operands.erase(Operands.begin() + 5);
5018 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5019 delete Op;
5020 }
5021 }
5022
Chris Lattner98986712010-01-14 22:21:20 +00005023 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005024}
5025
Jim Grosbach189610f2011-07-26 18:25:39 +00005026// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00005027
5028// return 'true' if register list contains non-low GPR registers,
5029// 'false' otherwise. If Reg is in the register list or is HiReg, set
5030// 'containsReg' to true.
5031static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
5032 unsigned HiReg, bool &containsReg) {
5033 containsReg = false;
5034 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5035 unsigned OpReg = Inst.getOperand(i).getReg();
5036 if (OpReg == Reg)
5037 containsReg = true;
5038 // Anything other than a low register isn't legal here.
5039 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
5040 return true;
5041 }
5042 return false;
5043}
5044
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005045// Check if the specified regisgter is in the register list of the inst,
5046// starting at the indicated operand number.
5047static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
5048 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5049 unsigned OpReg = Inst.getOperand(i).getReg();
5050 if (OpReg == Reg)
5051 return true;
5052 }
5053 return false;
5054}
5055
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005056// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
5057// the ARMInsts array) instead. Getting that here requires awkward
5058// API changes, though. Better way?
5059namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005060extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005061}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005062static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005063 return ARMInsts[Opcode];
5064}
5065
Jim Grosbach189610f2011-07-26 18:25:39 +00005066// FIXME: We would really like to be able to tablegen'erate this.
5067bool ARMAsmParser::
5068validateInstruction(MCInst &Inst,
5069 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005070 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005071 SMLoc Loc = Operands[0]->getStartLoc();
5072 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00005073 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
5074 // being allowed in IT blocks, but not being predicable. It just always
5075 // executes.
5076 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005077 unsigned bit = 1;
5078 if (ITState.FirstCond)
5079 ITState.FirstCond = false;
5080 else
Jim Grosbacha1109882011-09-02 23:22:08 +00005081 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005082 // The instruction must be predicable.
5083 if (!MCID.isPredicable())
5084 return Error(Loc, "instructions in IT block must be predicable");
5085 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
5086 unsigned ITCond = bit ? ITState.Cond :
5087 ARMCC::getOppositeCondition(ITState.Cond);
5088 if (Cond != ITCond) {
5089 // Find the condition code Operand to get its SMLoc information.
5090 SMLoc CondLoc;
5091 for (unsigned i = 1; i < Operands.size(); ++i)
5092 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
5093 CondLoc = Operands[i]->getStartLoc();
5094 return Error(CondLoc, "incorrect condition in IT block; got '" +
5095 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
5096 "', but expected '" +
5097 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
5098 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00005099 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005100 } else if (isThumbTwo() && MCID.isPredicable() &&
5101 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005102 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
5103 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005104 return Error(Loc, "predicated instructions must be in IT block");
5105
Jim Grosbach189610f2011-07-26 18:25:39 +00005106 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00005107 case ARM::LDRD:
5108 case ARM::LDRD_PRE:
5109 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005110 case ARM::LDREXD: {
5111 // Rt2 must be Rt + 1.
5112 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5113 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5114 if (Rt2 != Rt + 1)
5115 return Error(Operands[3]->getStartLoc(),
5116 "destination operands must be sequential");
5117 return false;
5118 }
Jim Grosbach14605d12011-08-11 20:28:23 +00005119 case ARM::STRD: {
5120 // Rt2 must be Rt + 1.
5121 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5122 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5123 if (Rt2 != Rt + 1)
5124 return Error(Operands[3]->getStartLoc(),
5125 "source operands must be sequential");
5126 return false;
5127 }
Jim Grosbach53642c52011-08-10 20:49:18 +00005128 case ARM::STRD_PRE:
5129 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005130 case ARM::STREXD: {
5131 // Rt2 must be Rt + 1.
5132 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5133 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
5134 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00005135 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00005136 "source operands must be sequential");
5137 return false;
5138 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005139 case ARM::SBFX:
5140 case ARM::UBFX: {
5141 // width must be in range [1, 32-lsb]
5142 unsigned lsb = Inst.getOperand(2).getImm();
5143 unsigned widthm1 = Inst.getOperand(3).getImm();
5144 if (widthm1 >= 32 - lsb)
5145 return Error(Operands[5]->getStartLoc(),
5146 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00005147 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005148 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005149 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005150 // If we're parsing Thumb2, the .w variant is available and handles
5151 // most cases that are normally illegal for a Thumb1 LDM
5152 // instruction. We'll make the transformation in processInstruction()
5153 // if necessary.
5154 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005155 // Thumb LDM instructions are writeback iff the base register is not
5156 // in the register list.
5157 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005158 bool hasWritebackToken =
5159 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5160 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00005161 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005162 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005163 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
5164 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005165 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005166 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005167 return Error(Operands[2]->getStartLoc(),
5168 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005169 // If we should not have writeback, there must not be a '!'. This is
5170 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00005171 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005172 return Error(Operands[3]->getStartLoc(),
5173 "writeback operator '!' not allowed when base register "
5174 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005175
5176 break;
5177 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005178 case ARM::t2LDMIA_UPD: {
5179 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
5180 return Error(Operands[4]->getStartLoc(),
5181 "writeback operator '!' not allowed when base register "
5182 "in register list");
5183 break;
5184 }
Jim Grosbach54026372011-11-10 23:17:11 +00005185 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
5186 // so only issue a diagnostic for thumb1. The instructions will be
5187 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005188 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005189 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005190 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
5191 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005192 return Error(Operands[2]->getStartLoc(),
5193 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005194 break;
5195 }
5196 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005197 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005198 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
5199 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005200 return Error(Operands[2]->getStartLoc(),
5201 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005202 break;
5203 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00005204 case ARM::tSTMIA_UPD: {
5205 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00005206 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00005207 return Error(Operands[4]->getStartLoc(),
5208 "registers must be in range r0-r7");
5209 break;
5210 }
Jim Grosbach189610f2011-07-26 18:25:39 +00005211 }
5212
5213 return false;
5214}
5215
Jim Grosbachd7433e22012-01-23 23:45:44 +00005216static unsigned getRealVSTOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach84defb52011-12-02 22:34:51 +00005217 switch(Opc) {
5218 default: assert(0 && "unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005219 // VST1LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005220 case ARM::VST1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
5221 case ARM::VST1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
5222 case ARM::VST1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
5223 case ARM::VST1LNdWB_register_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
5224 case ARM::VST1LNdWB_register_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
5225 case ARM::VST1LNdWB_register_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
5226 case ARM::VST1LNdAsm_8: Spacing = 1; return ARM::VST1LNd8;
5227 case ARM::VST1LNdAsm_16: Spacing = 1; return ARM::VST1LNd16;
5228 case ARM::VST1LNdAsm_32: Spacing = 1; return ARM::VST1LNd32;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005229
5230 // VST2LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005231 case ARM::VST2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
5232 case ARM::VST2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
5233 case ARM::VST2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
5234 case ARM::VST2LNqWB_fixed_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
5235 case ARM::VST2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005236
Jim Grosbach7945ead2012-01-24 00:43:12 +00005237 case ARM::VST2LNdWB_register_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
5238 case ARM::VST2LNdWB_register_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
5239 case ARM::VST2LNdWB_register_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
5240 case ARM::VST2LNqWB_register_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
5241 case ARM::VST2LNqWB_register_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005242
Jim Grosbach7945ead2012-01-24 00:43:12 +00005243 case ARM::VST2LNdAsm_8: Spacing = 1; return ARM::VST2LNd8;
5244 case ARM::VST2LNdAsm_16: Spacing = 1; return ARM::VST2LNd16;
5245 case ARM::VST2LNdAsm_32: Spacing = 1; return ARM::VST2LNd32;
5246 case ARM::VST2LNqAsm_16: Spacing = 2; return ARM::VST2LNq16;
5247 case ARM::VST2LNqAsm_32: Spacing = 2; return ARM::VST2LNq32;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005248
Jim Grosbach4adb1822012-01-24 00:07:41 +00005249 // VST3LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005250 case ARM::VST3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
5251 case ARM::VST3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
5252 case ARM::VST3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
5253 case ARM::VST3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNq16_UPD;
5254 case ARM::VST3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
5255 case ARM::VST3LNdWB_register_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
5256 case ARM::VST3LNdWB_register_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
5257 case ARM::VST3LNdWB_register_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
5258 case ARM::VST3LNqWB_register_Asm_16: Spacing = 2; return ARM::VST3LNq16_UPD;
5259 case ARM::VST3LNqWB_register_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
5260 case ARM::VST3LNdAsm_8: Spacing = 1; return ARM::VST3LNd8;
5261 case ARM::VST3LNdAsm_16: Spacing = 1; return ARM::VST3LNd16;
5262 case ARM::VST3LNdAsm_32: Spacing = 1; return ARM::VST3LNd32;
5263 case ARM::VST3LNqAsm_16: Spacing = 2; return ARM::VST3LNq16;
5264 case ARM::VST3LNqAsm_32: Spacing = 2; return ARM::VST3LNq32;
Jim Grosbach4adb1822012-01-24 00:07:41 +00005265
Jim Grosbachd7433e22012-01-23 23:45:44 +00005266 // VST3
Jim Grosbach7945ead2012-01-24 00:43:12 +00005267 case ARM::VST3dWB_fixed_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
5268 case ARM::VST3dWB_fixed_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
5269 case ARM::VST3dWB_fixed_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
5270 case ARM::VST3qWB_fixed_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
5271 case ARM::VST3qWB_fixed_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
5272 case ARM::VST3qWB_fixed_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
5273 case ARM::VST3dWB_register_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
5274 case ARM::VST3dWB_register_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
5275 case ARM::VST3dWB_register_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
5276 case ARM::VST3qWB_register_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
5277 case ARM::VST3qWB_register_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
5278 case ARM::VST3qWB_register_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
5279 case ARM::VST3dAsm_8: Spacing = 1; return ARM::VST3d8;
5280 case ARM::VST3dAsm_16: Spacing = 1; return ARM::VST3d16;
5281 case ARM::VST3dAsm_32: Spacing = 1; return ARM::VST3d32;
5282 case ARM::VST3qAsm_8: Spacing = 2; return ARM::VST3q8;
5283 case ARM::VST3qAsm_16: Spacing = 2; return ARM::VST3q16;
5284 case ARM::VST3qAsm_32: Spacing = 2; return ARM::VST3q32;
Jim Grosbach539aab72012-01-24 00:58:13 +00005285
Jim Grosbach88a54de2012-01-24 18:53:13 +00005286 // VST4LN
5287 case ARM::VST4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD;
5288 case ARM::VST4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD;
5289 case ARM::VST4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD;
5290 case ARM::VST4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNq16_UPD;
5291 case ARM::VST4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD;
5292 case ARM::VST4LNdWB_register_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD;
5293 case ARM::VST4LNdWB_register_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD;
5294 case ARM::VST4LNdWB_register_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD;
5295 case ARM::VST4LNqWB_register_Asm_16: Spacing = 2; return ARM::VST4LNq16_UPD;
5296 case ARM::VST4LNqWB_register_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD;
5297 case ARM::VST4LNdAsm_8: Spacing = 1; return ARM::VST4LNd8;
5298 case ARM::VST4LNdAsm_16: Spacing = 1; return ARM::VST4LNd16;
5299 case ARM::VST4LNdAsm_32: Spacing = 1; return ARM::VST4LNd32;
5300 case ARM::VST4LNqAsm_16: Spacing = 2; return ARM::VST4LNq16;
5301 case ARM::VST4LNqAsm_32: Spacing = 2; return ARM::VST4LNq32;
5302
Jim Grosbach539aab72012-01-24 00:58:13 +00005303 // VST4
5304 case ARM::VST4dWB_fixed_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
5305 case ARM::VST4dWB_fixed_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
5306 case ARM::VST4dWB_fixed_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
5307 case ARM::VST4qWB_fixed_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
5308 case ARM::VST4qWB_fixed_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
5309 case ARM::VST4qWB_fixed_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
5310 case ARM::VST4dWB_register_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
5311 case ARM::VST4dWB_register_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
5312 case ARM::VST4dWB_register_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
5313 case ARM::VST4qWB_register_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
5314 case ARM::VST4qWB_register_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
5315 case ARM::VST4qWB_register_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
5316 case ARM::VST4dAsm_8: Spacing = 1; return ARM::VST4d8;
5317 case ARM::VST4dAsm_16: Spacing = 1; return ARM::VST4d16;
5318 case ARM::VST4dAsm_32: Spacing = 1; return ARM::VST4d32;
5319 case ARM::VST4qAsm_8: Spacing = 2; return ARM::VST4q8;
5320 case ARM::VST4qAsm_16: Spacing = 2; return ARM::VST4q16;
5321 case ARM::VST4qAsm_32: Spacing = 2; return ARM::VST4q32;
Jim Grosbach84defb52011-12-02 22:34:51 +00005322 }
5323}
5324
Jim Grosbachd7433e22012-01-23 23:45:44 +00005325static unsigned getRealVLDOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005326 switch(Opc) {
5327 default: assert(0 && "unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005328 // VLD1LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005329 case ARM::VLD1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
5330 case ARM::VLD1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
5331 case ARM::VLD1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
5332 case ARM::VLD1LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
5333 case ARM::VLD1LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
5334 case ARM::VLD1LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
5335 case ARM::VLD1LNdAsm_8: Spacing = 1; return ARM::VLD1LNd8;
5336 case ARM::VLD1LNdAsm_16: Spacing = 1; return ARM::VLD1LNd16;
5337 case ARM::VLD1LNdAsm_32: Spacing = 1; return ARM::VLD1LNd32;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005338
5339 // VLD2LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005340 case ARM::VLD2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
5341 case ARM::VLD2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
5342 case ARM::VLD2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
5343 case ARM::VLD2LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNq16_UPD;
5344 case ARM::VLD2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
5345 case ARM::VLD2LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
5346 case ARM::VLD2LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
5347 case ARM::VLD2LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
5348 case ARM::VLD2LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD2LNq16_UPD;
5349 case ARM::VLD2LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
5350 case ARM::VLD2LNdAsm_8: Spacing = 1; return ARM::VLD2LNd8;
5351 case ARM::VLD2LNdAsm_16: Spacing = 1; return ARM::VLD2LNd16;
5352 case ARM::VLD2LNdAsm_32: Spacing = 1; return ARM::VLD2LNd32;
5353 case ARM::VLD2LNqAsm_16: Spacing = 2; return ARM::VLD2LNq16;
5354 case ARM::VLD2LNqAsm_32: Spacing = 2; return ARM::VLD2LNq32;
Jim Grosbach3a678af2012-01-23 21:53:26 +00005355
Jim Grosbach5e59f7e2012-01-24 23:47:04 +00005356 // VLD3DUP
5357 case ARM::VLD3DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD;
5358 case ARM::VLD3DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD;
5359 case ARM::VLD3DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD;
5360 case ARM::VLD3DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPq8_UPD;
5361 case ARM::VLD3DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPq16_UPD;
5362 case ARM::VLD3DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD;
5363 case ARM::VLD3DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD;
5364 case ARM::VLD3DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD;
5365 case ARM::VLD3DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD;
5366 case ARM::VLD3DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD3DUPq8_UPD;
5367 case ARM::VLD3DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD3DUPq16_UPD;
5368 case ARM::VLD3DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD;
5369 case ARM::VLD3DUPdAsm_8: Spacing = 1; return ARM::VLD3DUPd8;
5370 case ARM::VLD3DUPdAsm_16: Spacing = 1; return ARM::VLD3DUPd16;
5371 case ARM::VLD3DUPdAsm_32: Spacing = 1; return ARM::VLD3DUPd32;
5372 case ARM::VLD3DUPqAsm_8: Spacing = 2; return ARM::VLD3DUPq8;
5373 case ARM::VLD3DUPqAsm_16: Spacing = 2; return ARM::VLD3DUPq16;
5374 case ARM::VLD3DUPqAsm_32: Spacing = 2; return ARM::VLD3DUPq32;
5375
Jim Grosbach3a678af2012-01-23 21:53:26 +00005376 // VLD3LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005377 case ARM::VLD3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
5378 case ARM::VLD3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
5379 case ARM::VLD3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
5380 case ARM::VLD3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNq16_UPD;
5381 case ARM::VLD3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
5382 case ARM::VLD3LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
5383 case ARM::VLD3LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
5384 case ARM::VLD3LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
5385 case ARM::VLD3LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD3LNq16_UPD;
5386 case ARM::VLD3LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
5387 case ARM::VLD3LNdAsm_8: Spacing = 1; return ARM::VLD3LNd8;
5388 case ARM::VLD3LNdAsm_16: Spacing = 1; return ARM::VLD3LNd16;
5389 case ARM::VLD3LNdAsm_32: Spacing = 1; return ARM::VLD3LNd32;
5390 case ARM::VLD3LNqAsm_16: Spacing = 2; return ARM::VLD3LNq16;
5391 case ARM::VLD3LNqAsm_32: Spacing = 2; return ARM::VLD3LNq32;
Jim Grosbachc387fc62012-01-23 23:20:46 +00005392
5393 // VLD3
Jim Grosbach7945ead2012-01-24 00:43:12 +00005394 case ARM::VLD3dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
5395 case ARM::VLD3dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
5396 case ARM::VLD3dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
5397 case ARM::VLD3qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
5398 case ARM::VLD3qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
5399 case ARM::VLD3qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
5400 case ARM::VLD3dWB_register_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
5401 case ARM::VLD3dWB_register_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
5402 case ARM::VLD3dWB_register_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
5403 case ARM::VLD3qWB_register_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
5404 case ARM::VLD3qWB_register_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
5405 case ARM::VLD3qWB_register_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
5406 case ARM::VLD3dAsm_8: Spacing = 1; return ARM::VLD3d8;
5407 case ARM::VLD3dAsm_16: Spacing = 1; return ARM::VLD3d16;
5408 case ARM::VLD3dAsm_32: Spacing = 1; return ARM::VLD3d32;
5409 case ARM::VLD3qAsm_8: Spacing = 2; return ARM::VLD3q8;
5410 case ARM::VLD3qAsm_16: Spacing = 2; return ARM::VLD3q16;
5411 case ARM::VLD3qAsm_32: Spacing = 2; return ARM::VLD3q32;
Jim Grosbach8abe7e32012-01-24 00:43:17 +00005412
Jim Grosbache983a132012-01-24 18:37:25 +00005413 // VLD4LN
5414 case ARM::VLD4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD;
5415 case ARM::VLD4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
5416 case ARM::VLD4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
5417 case ARM::VLD4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNq16_UPD;
5418 case ARM::VLD4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
5419 case ARM::VLD4LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD;
5420 case ARM::VLD4LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
5421 case ARM::VLD4LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
5422 case ARM::VLD4LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD4LNq16_UPD;
5423 case ARM::VLD4LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
5424 case ARM::VLD4LNdAsm_8: Spacing = 1; return ARM::VLD4LNd8;
5425 case ARM::VLD4LNdAsm_16: Spacing = 1; return ARM::VLD4LNd16;
5426 case ARM::VLD4LNdAsm_32: Spacing = 1; return ARM::VLD4LNd32;
5427 case ARM::VLD4LNqAsm_16: Spacing = 2; return ARM::VLD4LNq16;
5428 case ARM::VLD4LNqAsm_32: Spacing = 2; return ARM::VLD4LNq32;
5429
Jim Grosbach8abe7e32012-01-24 00:43:17 +00005430 // VLD4
5431 case ARM::VLD4dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
5432 case ARM::VLD4dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
5433 case ARM::VLD4dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
5434 case ARM::VLD4qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
5435 case ARM::VLD4qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
5436 case ARM::VLD4qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
5437 case ARM::VLD4dWB_register_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
5438 case ARM::VLD4dWB_register_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
5439 case ARM::VLD4dWB_register_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
5440 case ARM::VLD4qWB_register_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
5441 case ARM::VLD4qWB_register_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
5442 case ARM::VLD4qWB_register_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
5443 case ARM::VLD4dAsm_8: Spacing = 1; return ARM::VLD4d8;
5444 case ARM::VLD4dAsm_16: Spacing = 1; return ARM::VLD4d16;
5445 case ARM::VLD4dAsm_32: Spacing = 1; return ARM::VLD4d32;
5446 case ARM::VLD4qAsm_8: Spacing = 2; return ARM::VLD4q8;
5447 case ARM::VLD4qAsm_16: Spacing = 2; return ARM::VLD4q16;
5448 case ARM::VLD4qAsm_32: Spacing = 2; return ARM::VLD4q32;
Jim Grosbach7636bf62011-12-02 00:35:16 +00005449 }
5450}
5451
Jim Grosbach83ec8772011-11-10 23:42:14 +00005452bool ARMAsmParser::
Jim Grosbachf8fce712011-08-11 17:35:48 +00005453processInstruction(MCInst &Inst,
5454 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5455 switch (Inst.getOpcode()) {
Jim Grosbach0b4c6732012-01-18 22:46:46 +00005456 // Aliases for alternate PC+imm syntax of LDR instructions.
5457 case ARM::t2LDRpcrel:
5458 Inst.setOpcode(ARM::t2LDRpci);
5459 return true;
5460 case ARM::t2LDRBpcrel:
5461 Inst.setOpcode(ARM::t2LDRBpci);
5462 return true;
5463 case ARM::t2LDRHpcrel:
5464 Inst.setOpcode(ARM::t2LDRHpci);
5465 return true;
5466 case ARM::t2LDRSBpcrel:
5467 Inst.setOpcode(ARM::t2LDRSBpci);
5468 return true;
5469 case ARM::t2LDRSHpcrel:
5470 Inst.setOpcode(ARM::t2LDRSHpci);
5471 return true;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005472 // Handle NEON VST complex aliases.
Jim Grosbach8b31f952012-01-23 19:39:08 +00005473 case ARM::VST1LNdWB_register_Asm_8:
5474 case ARM::VST1LNdWB_register_Asm_16:
5475 case ARM::VST1LNdWB_register_Asm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005476 MCInst TmpInst;
5477 // Shuffle the operands around so the lane index operand is in the
5478 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005479 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005480 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005481 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5482 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5483 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5484 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5485 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5486 TmpInst.addOperand(Inst.getOperand(1)); // lane
5487 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5488 TmpInst.addOperand(Inst.getOperand(6));
5489 Inst = TmpInst;
5490 return true;
5491 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005492
Jim Grosbach8b31f952012-01-23 19:39:08 +00005493 case ARM::VST2LNdWB_register_Asm_8:
5494 case ARM::VST2LNdWB_register_Asm_16:
5495 case ARM::VST2LNdWB_register_Asm_32:
5496 case ARM::VST2LNqWB_register_Asm_16:
5497 case ARM::VST2LNqWB_register_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005498 MCInst TmpInst;
5499 // Shuffle the operands around so the lane index operand is in the
5500 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005501 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005502 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005503 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5504 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5505 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5506 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5507 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005508 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5509 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005510 TmpInst.addOperand(Inst.getOperand(1)); // lane
5511 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5512 TmpInst.addOperand(Inst.getOperand(6));
5513 Inst = TmpInst;
5514 return true;
5515 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005516
5517 case ARM::VST3LNdWB_register_Asm_8:
5518 case ARM::VST3LNdWB_register_Asm_16:
5519 case ARM::VST3LNdWB_register_Asm_32:
5520 case ARM::VST3LNqWB_register_Asm_16:
5521 case ARM::VST3LNqWB_register_Asm_32: {
5522 MCInst TmpInst;
5523 // Shuffle the operands around so the lane index operand is in the
5524 // right place.
5525 unsigned Spacing;
5526 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5527 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5528 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5529 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5530 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5531 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5532 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5533 Spacing));
5534 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5535 Spacing * 2));
5536 TmpInst.addOperand(Inst.getOperand(1)); // lane
5537 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5538 TmpInst.addOperand(Inst.getOperand(6));
5539 Inst = TmpInst;
5540 return true;
5541 }
5542
Jim Grosbach88a54de2012-01-24 18:53:13 +00005543 case ARM::VST4LNdWB_register_Asm_8:
5544 case ARM::VST4LNdWB_register_Asm_16:
5545 case ARM::VST4LNdWB_register_Asm_32:
5546 case ARM::VST4LNqWB_register_Asm_16:
5547 case ARM::VST4LNqWB_register_Asm_32: {
5548 MCInst TmpInst;
5549 // Shuffle the operands around so the lane index operand is in the
5550 // right place.
5551 unsigned Spacing;
5552 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5553 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5554 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5555 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5556 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5557 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5558 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5559 Spacing));
5560 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5561 Spacing * 2));
5562 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5563 Spacing * 3));
5564 TmpInst.addOperand(Inst.getOperand(1)); // lane
5565 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5566 TmpInst.addOperand(Inst.getOperand(6));
5567 Inst = TmpInst;
5568 return true;
5569 }
5570
Jim Grosbach8b31f952012-01-23 19:39:08 +00005571 case ARM::VST1LNdWB_fixed_Asm_8:
5572 case ARM::VST1LNdWB_fixed_Asm_16:
5573 case ARM::VST1LNdWB_fixed_Asm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005574 MCInst TmpInst;
5575 // Shuffle the operands around so the lane index operand is in the
5576 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005577 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005578 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005579 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5580 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5581 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5582 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5583 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5584 TmpInst.addOperand(Inst.getOperand(1)); // lane
5585 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5586 TmpInst.addOperand(Inst.getOperand(5));
5587 Inst = TmpInst;
5588 return true;
5589 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005590
Jim Grosbach8b31f952012-01-23 19:39:08 +00005591 case ARM::VST2LNdWB_fixed_Asm_8:
5592 case ARM::VST2LNdWB_fixed_Asm_16:
5593 case ARM::VST2LNdWB_fixed_Asm_32:
5594 case ARM::VST2LNqWB_fixed_Asm_16:
5595 case ARM::VST2LNqWB_fixed_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005596 MCInst TmpInst;
5597 // Shuffle the operands around so the lane index operand is in the
5598 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005599 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005600 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005601 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5602 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5603 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5604 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5605 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005606 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5607 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005608 TmpInst.addOperand(Inst.getOperand(1)); // lane
5609 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5610 TmpInst.addOperand(Inst.getOperand(5));
5611 Inst = TmpInst;
5612 return true;
5613 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005614
5615 case ARM::VST3LNdWB_fixed_Asm_8:
5616 case ARM::VST3LNdWB_fixed_Asm_16:
5617 case ARM::VST3LNdWB_fixed_Asm_32:
5618 case ARM::VST3LNqWB_fixed_Asm_16:
5619 case ARM::VST3LNqWB_fixed_Asm_32: {
5620 MCInst TmpInst;
5621 // Shuffle the operands around so the lane index operand is in the
5622 // right place.
5623 unsigned Spacing;
5624 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5625 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5626 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5627 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5628 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5629 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5630 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5631 Spacing));
5632 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5633 Spacing * 2));
5634 TmpInst.addOperand(Inst.getOperand(1)); // lane
5635 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5636 TmpInst.addOperand(Inst.getOperand(5));
5637 Inst = TmpInst;
5638 return true;
5639 }
5640
Jim Grosbach88a54de2012-01-24 18:53:13 +00005641 case ARM::VST4LNdWB_fixed_Asm_8:
5642 case ARM::VST4LNdWB_fixed_Asm_16:
5643 case ARM::VST4LNdWB_fixed_Asm_32:
5644 case ARM::VST4LNqWB_fixed_Asm_16:
5645 case ARM::VST4LNqWB_fixed_Asm_32: {
5646 MCInst TmpInst;
5647 // Shuffle the operands around so the lane index operand is in the
5648 // right place.
5649 unsigned Spacing;
5650 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5651 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5652 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5653 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5654 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5655 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5656 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5657 Spacing));
5658 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5659 Spacing * 2));
5660 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5661 Spacing * 3));
5662 TmpInst.addOperand(Inst.getOperand(1)); // lane
5663 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5664 TmpInst.addOperand(Inst.getOperand(5));
5665 Inst = TmpInst;
5666 return true;
5667 }
5668
Jim Grosbach8b31f952012-01-23 19:39:08 +00005669 case ARM::VST1LNdAsm_8:
5670 case ARM::VST1LNdAsm_16:
5671 case ARM::VST1LNdAsm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005672 MCInst TmpInst;
5673 // Shuffle the operands around so the lane index operand is in the
5674 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005675 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005676 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005677 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5678 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5679 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5680 TmpInst.addOperand(Inst.getOperand(1)); // lane
5681 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5682 TmpInst.addOperand(Inst.getOperand(5));
5683 Inst = TmpInst;
5684 return true;
5685 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005686
Jim Grosbach8b31f952012-01-23 19:39:08 +00005687 case ARM::VST2LNdAsm_8:
5688 case ARM::VST2LNdAsm_16:
5689 case ARM::VST2LNdAsm_32:
5690 case ARM::VST2LNqAsm_16:
5691 case ARM::VST2LNqAsm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005692 MCInst TmpInst;
5693 // Shuffle the operands around so the lane index operand is in the
5694 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005695 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005696 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005697 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5698 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5699 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005700 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5701 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005702 TmpInst.addOperand(Inst.getOperand(1)); // lane
5703 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5704 TmpInst.addOperand(Inst.getOperand(5));
5705 Inst = TmpInst;
5706 return true;
5707 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005708
5709 case ARM::VST3LNdAsm_8:
5710 case ARM::VST3LNdAsm_16:
5711 case ARM::VST3LNdAsm_32:
5712 case ARM::VST3LNqAsm_16:
5713 case ARM::VST3LNqAsm_32: {
5714 MCInst TmpInst;
5715 // Shuffle the operands around so the lane index operand is in the
5716 // right place.
5717 unsigned Spacing;
5718 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5719 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5720 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5721 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5722 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5723 Spacing));
5724 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5725 Spacing * 2));
5726 TmpInst.addOperand(Inst.getOperand(1)); // lane
5727 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5728 TmpInst.addOperand(Inst.getOperand(5));
5729 Inst = TmpInst;
5730 return true;
5731 }
5732
Jim Grosbach88a54de2012-01-24 18:53:13 +00005733 case ARM::VST4LNdAsm_8:
5734 case ARM::VST4LNdAsm_16:
5735 case ARM::VST4LNdAsm_32:
5736 case ARM::VST4LNqAsm_16:
5737 case ARM::VST4LNqAsm_32: {
5738 MCInst TmpInst;
5739 // Shuffle the operands around so the lane index operand is in the
5740 // right place.
5741 unsigned Spacing;
5742 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5743 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5744 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5745 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5746 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5747 Spacing));
5748 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5749 Spacing * 2));
5750 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5751 Spacing * 3));
5752 TmpInst.addOperand(Inst.getOperand(1)); // lane
5753 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5754 TmpInst.addOperand(Inst.getOperand(5));
5755 Inst = TmpInst;
5756 return true;
5757 }
5758
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005759 // Handle NEON VLD complex aliases.
Jim Grosbach8b31f952012-01-23 19:39:08 +00005760 case ARM::VLD1LNdWB_register_Asm_8:
5761 case ARM::VLD1LNdWB_register_Asm_16:
5762 case ARM::VLD1LNdWB_register_Asm_32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005763 MCInst TmpInst;
5764 // Shuffle the operands around so the lane index operand is in the
5765 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005766 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005767 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005768 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5769 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5770 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5771 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5772 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5773 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5774 TmpInst.addOperand(Inst.getOperand(1)); // lane
5775 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5776 TmpInst.addOperand(Inst.getOperand(6));
5777 Inst = TmpInst;
5778 return true;
5779 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005780
Jim Grosbach8b31f952012-01-23 19:39:08 +00005781 case ARM::VLD2LNdWB_register_Asm_8:
5782 case ARM::VLD2LNdWB_register_Asm_16:
5783 case ARM::VLD2LNdWB_register_Asm_32:
5784 case ARM::VLD2LNqWB_register_Asm_16:
5785 case ARM::VLD2LNqWB_register_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005786 MCInst TmpInst;
5787 // Shuffle the operands around so the lane index operand is in the
5788 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005789 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005790 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005791 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005792 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5793 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005794 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5795 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5796 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5797 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5798 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005799 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5800 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005801 TmpInst.addOperand(Inst.getOperand(1)); // lane
5802 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5803 TmpInst.addOperand(Inst.getOperand(6));
5804 Inst = TmpInst;
5805 return true;
5806 }
5807
Jim Grosbach3a678af2012-01-23 21:53:26 +00005808 case ARM::VLD3LNdWB_register_Asm_8:
5809 case ARM::VLD3LNdWB_register_Asm_16:
5810 case ARM::VLD3LNdWB_register_Asm_32:
5811 case ARM::VLD3LNqWB_register_Asm_16:
5812 case ARM::VLD3LNqWB_register_Asm_32: {
5813 MCInst TmpInst;
5814 // Shuffle the operands around so the lane index operand is in the
5815 // right place.
5816 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005817 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005818 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5819 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5820 Spacing));
5821 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005822 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005823 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5824 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5825 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5826 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5827 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5828 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5829 Spacing));
5830 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005831 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005832 TmpInst.addOperand(Inst.getOperand(1)); // lane
5833 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5834 TmpInst.addOperand(Inst.getOperand(6));
5835 Inst = TmpInst;
5836 return true;
5837 }
5838
Jim Grosbache983a132012-01-24 18:37:25 +00005839 case ARM::VLD4LNdWB_register_Asm_8:
5840 case ARM::VLD4LNdWB_register_Asm_16:
5841 case ARM::VLD4LNdWB_register_Asm_32:
5842 case ARM::VLD4LNqWB_register_Asm_16:
5843 case ARM::VLD4LNqWB_register_Asm_32: {
5844 MCInst TmpInst;
5845 // Shuffle the operands around so the lane index operand is in the
5846 // right place.
5847 unsigned Spacing;
5848 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
5849 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5850 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5851 Spacing));
5852 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5853 Spacing * 2));
5854 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5855 Spacing * 3));
5856 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5857 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5858 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5859 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5860 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5861 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5862 Spacing));
5863 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5864 Spacing * 2));
5865 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5866 Spacing * 3));
5867 TmpInst.addOperand(Inst.getOperand(1)); // lane
5868 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5869 TmpInst.addOperand(Inst.getOperand(6));
5870 Inst = TmpInst;
5871 return true;
5872 }
5873
Jim Grosbach8b31f952012-01-23 19:39:08 +00005874 case ARM::VLD1LNdWB_fixed_Asm_8:
5875 case ARM::VLD1LNdWB_fixed_Asm_16:
5876 case ARM::VLD1LNdWB_fixed_Asm_32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005877 MCInst TmpInst;
5878 // Shuffle the operands around so the lane index operand is in the
5879 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005880 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005881 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005882 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5883 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5884 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5885 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5886 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5887 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5888 TmpInst.addOperand(Inst.getOperand(1)); // lane
5889 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5890 TmpInst.addOperand(Inst.getOperand(5));
5891 Inst = TmpInst;
5892 return true;
5893 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005894
Jim Grosbach8b31f952012-01-23 19:39:08 +00005895 case ARM::VLD2LNdWB_fixed_Asm_8:
5896 case ARM::VLD2LNdWB_fixed_Asm_16:
5897 case ARM::VLD2LNdWB_fixed_Asm_32:
5898 case ARM::VLD2LNqWB_fixed_Asm_16:
5899 case ARM::VLD2LNqWB_fixed_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005900 MCInst TmpInst;
5901 // Shuffle the operands around so the lane index operand is in the
5902 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005903 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005904 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005905 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005906 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5907 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005908 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5909 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5910 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5911 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5912 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005913 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5914 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005915 TmpInst.addOperand(Inst.getOperand(1)); // lane
5916 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5917 TmpInst.addOperand(Inst.getOperand(5));
5918 Inst = TmpInst;
5919 return true;
5920 }
5921
Jim Grosbach3a678af2012-01-23 21:53:26 +00005922 case ARM::VLD3LNdWB_fixed_Asm_8:
5923 case ARM::VLD3LNdWB_fixed_Asm_16:
5924 case ARM::VLD3LNdWB_fixed_Asm_32:
5925 case ARM::VLD3LNqWB_fixed_Asm_16:
5926 case ARM::VLD3LNqWB_fixed_Asm_32: {
5927 MCInst TmpInst;
5928 // Shuffle the operands around so the lane index operand is in the
5929 // right place.
5930 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005931 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005932 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5933 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5934 Spacing));
5935 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005936 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005937 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5938 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5939 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5940 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5941 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5942 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5943 Spacing));
5944 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005945 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005946 TmpInst.addOperand(Inst.getOperand(1)); // lane
5947 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5948 TmpInst.addOperand(Inst.getOperand(5));
5949 Inst = TmpInst;
5950 return true;
5951 }
5952
Jim Grosbache983a132012-01-24 18:37:25 +00005953 case ARM::VLD4LNdWB_fixed_Asm_8:
5954 case ARM::VLD4LNdWB_fixed_Asm_16:
5955 case ARM::VLD4LNdWB_fixed_Asm_32:
5956 case ARM::VLD4LNqWB_fixed_Asm_16:
5957 case ARM::VLD4LNqWB_fixed_Asm_32: {
5958 MCInst TmpInst;
5959 // Shuffle the operands around so the lane index operand is in the
5960 // right place.
5961 unsigned Spacing;
5962 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
5963 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5964 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5965 Spacing));
5966 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5967 Spacing * 2));
5968 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5969 Spacing * 3));
5970 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5971 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5972 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5973 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5974 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5975 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5976 Spacing));
5977 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5978 Spacing * 2));
5979 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5980 Spacing * 3));
5981 TmpInst.addOperand(Inst.getOperand(1)); // lane
5982 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5983 TmpInst.addOperand(Inst.getOperand(5));
5984 Inst = TmpInst;
5985 return true;
5986 }
5987
Jim Grosbach8b31f952012-01-23 19:39:08 +00005988 case ARM::VLD1LNdAsm_8:
5989 case ARM::VLD1LNdAsm_16:
5990 case ARM::VLD1LNdAsm_32: {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005991 MCInst TmpInst;
5992 // Shuffle the operands around so the lane index operand is in the
5993 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005994 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005995 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach7636bf62011-12-02 00:35:16 +00005996 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5997 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5998 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5999 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6000 TmpInst.addOperand(Inst.getOperand(1)); // lane
6001 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6002 TmpInst.addOperand(Inst.getOperand(5));
6003 Inst = TmpInst;
6004 return true;
6005 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006006
Jim Grosbach8b31f952012-01-23 19:39:08 +00006007 case ARM::VLD2LNdAsm_8:
6008 case ARM::VLD2LNdAsm_16:
6009 case ARM::VLD2LNdAsm_32:
6010 case ARM::VLD2LNqAsm_16:
6011 case ARM::VLD2LNqAsm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006012 MCInst TmpInst;
6013 // Shuffle the operands around so the lane index operand is in the
6014 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006015 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006016 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006017 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006018 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6019 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006020 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6021 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6022 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006023 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6024 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006025 TmpInst.addOperand(Inst.getOperand(1)); // lane
6026 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6027 TmpInst.addOperand(Inst.getOperand(5));
6028 Inst = TmpInst;
6029 return true;
6030 }
Jim Grosbach3a678af2012-01-23 21:53:26 +00006031
6032 case ARM::VLD3LNdAsm_8:
6033 case ARM::VLD3LNdAsm_16:
6034 case ARM::VLD3LNdAsm_32:
6035 case ARM::VLD3LNqAsm_16:
6036 case ARM::VLD3LNqAsm_32: {
6037 MCInst TmpInst;
6038 // Shuffle the operands around so the lane index operand is in the
6039 // right place.
6040 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006041 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006042 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6043 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6044 Spacing));
6045 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006046 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006047 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6048 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6049 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6050 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6051 Spacing));
6052 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006053 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006054 TmpInst.addOperand(Inst.getOperand(1)); // lane
6055 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6056 TmpInst.addOperand(Inst.getOperand(5));
6057 Inst = TmpInst;
6058 return true;
6059 }
6060
Jim Grosbache983a132012-01-24 18:37:25 +00006061 case ARM::VLD4LNdAsm_8:
6062 case ARM::VLD4LNdAsm_16:
6063 case ARM::VLD4LNdAsm_32:
6064 case ARM::VLD4LNqAsm_16:
6065 case ARM::VLD4LNqAsm_32: {
6066 MCInst TmpInst;
6067 // Shuffle the operands around so the lane index operand is in the
6068 // right place.
6069 unsigned Spacing;
6070 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6071 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6072 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6073 Spacing));
6074 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6075 Spacing * 2));
6076 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6077 Spacing * 3));
6078 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6079 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6080 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6081 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6082 Spacing));
6083 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6084 Spacing * 2));
6085 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6086 Spacing * 3));
6087 TmpInst.addOperand(Inst.getOperand(1)); // lane
6088 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6089 TmpInst.addOperand(Inst.getOperand(5));
6090 Inst = TmpInst;
6091 return true;
6092 }
6093
Jim Grosbach5e59f7e2012-01-24 23:47:04 +00006094 // VLD3DUP single 3-element structure to all lanes instructions.
6095 case ARM::VLD3DUPdAsm_8:
6096 case ARM::VLD3DUPdAsm_16:
6097 case ARM::VLD3DUPdAsm_32:
6098 case ARM::VLD3DUPqAsm_8:
6099 case ARM::VLD3DUPqAsm_16:
6100 case ARM::VLD3DUPqAsm_32: {
6101 MCInst TmpInst;
6102 unsigned Spacing;
6103 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6104 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6105 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6106 Spacing));
6107 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6108 Spacing * 2));
6109 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6110 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6111 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6112 TmpInst.addOperand(Inst.getOperand(4));
6113 Inst = TmpInst;
6114 return true;
6115 }
6116
6117 case ARM::VLD3DUPdWB_fixed_Asm_8:
6118 case ARM::VLD3DUPdWB_fixed_Asm_16:
6119 case ARM::VLD3DUPdWB_fixed_Asm_32:
6120 case ARM::VLD3DUPqWB_fixed_Asm_8:
6121 case ARM::VLD3DUPqWB_fixed_Asm_16:
6122 case ARM::VLD3DUPqWB_fixed_Asm_32: {
6123 MCInst TmpInst;
6124 unsigned Spacing;
6125 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6126 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6127 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6128 Spacing));
6129 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6130 Spacing * 2));
6131 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6132 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6133 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6134 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6135 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6136 TmpInst.addOperand(Inst.getOperand(4));
6137 Inst = TmpInst;
6138 return true;
6139 }
6140
6141 case ARM::VLD3DUPdWB_register_Asm_8:
6142 case ARM::VLD3DUPdWB_register_Asm_16:
6143 case ARM::VLD3DUPdWB_register_Asm_32:
6144 case ARM::VLD3DUPqWB_register_Asm_8:
6145 case ARM::VLD3DUPqWB_register_Asm_16:
6146 case ARM::VLD3DUPqWB_register_Asm_32: {
6147 MCInst TmpInst;
6148 unsigned Spacing;
6149 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6150 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6151 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6152 Spacing));
6153 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6154 Spacing * 2));
6155 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6156 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6157 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6158 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6159 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6160 TmpInst.addOperand(Inst.getOperand(5));
6161 Inst = TmpInst;
6162 return true;
6163 }
6164
Jim Grosbachc387fc62012-01-23 23:20:46 +00006165 // VLD3 multiple 3-element structure instructions.
6166 case ARM::VLD3dAsm_8:
6167 case ARM::VLD3dAsm_16:
6168 case ARM::VLD3dAsm_32:
6169 case ARM::VLD3qAsm_8:
6170 case ARM::VLD3qAsm_16:
6171 case ARM::VLD3qAsm_32: {
6172 MCInst TmpInst;
6173 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006174 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00006175 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6176 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6177 Spacing));
6178 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6179 Spacing * 2));
6180 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6181 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6182 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6183 TmpInst.addOperand(Inst.getOperand(4));
6184 Inst = TmpInst;
6185 return true;
6186 }
6187
6188 case ARM::VLD3dWB_fixed_Asm_8:
6189 case ARM::VLD3dWB_fixed_Asm_16:
6190 case ARM::VLD3dWB_fixed_Asm_32:
6191 case ARM::VLD3qWB_fixed_Asm_8:
6192 case ARM::VLD3qWB_fixed_Asm_16:
6193 case ARM::VLD3qWB_fixed_Asm_32: {
6194 MCInst TmpInst;
6195 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006196 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00006197 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6198 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6199 Spacing));
6200 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6201 Spacing * 2));
6202 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6203 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6204 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6205 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6206 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6207 TmpInst.addOperand(Inst.getOperand(4));
6208 Inst = TmpInst;
6209 return true;
6210 }
6211
6212 case ARM::VLD3dWB_register_Asm_8:
6213 case ARM::VLD3dWB_register_Asm_16:
6214 case ARM::VLD3dWB_register_Asm_32:
6215 case ARM::VLD3qWB_register_Asm_8:
6216 case ARM::VLD3qWB_register_Asm_16:
6217 case ARM::VLD3qWB_register_Asm_32: {
6218 MCInst TmpInst;
6219 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006220 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00006221 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6222 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6223 Spacing));
6224 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6225 Spacing * 2));
6226 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6227 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6228 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6229 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6230 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6231 TmpInst.addOperand(Inst.getOperand(5));
6232 Inst = TmpInst;
6233 return true;
6234 }
6235
Jim Grosbach8abe7e32012-01-24 00:43:17 +00006236 // VLD4 multiple 3-element structure instructions.
6237 case ARM::VLD4dAsm_8:
6238 case ARM::VLD4dAsm_16:
6239 case ARM::VLD4dAsm_32:
6240 case ARM::VLD4qAsm_8:
6241 case ARM::VLD4qAsm_16:
6242 case ARM::VLD4qAsm_32: {
6243 MCInst TmpInst;
6244 unsigned Spacing;
6245 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6246 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6247 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6248 Spacing));
6249 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6250 Spacing * 2));
6251 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6252 Spacing * 3));
6253 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6254 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6255 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6256 TmpInst.addOperand(Inst.getOperand(4));
6257 Inst = TmpInst;
6258 return true;
6259 }
6260
6261 case ARM::VLD4dWB_fixed_Asm_8:
6262 case ARM::VLD4dWB_fixed_Asm_16:
6263 case ARM::VLD4dWB_fixed_Asm_32:
6264 case ARM::VLD4qWB_fixed_Asm_8:
6265 case ARM::VLD4qWB_fixed_Asm_16:
6266 case ARM::VLD4qWB_fixed_Asm_32: {
6267 MCInst TmpInst;
6268 unsigned Spacing;
6269 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6270 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6271 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6272 Spacing));
6273 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6274 Spacing * 2));
6275 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6276 Spacing * 3));
6277 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6278 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6279 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6280 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6281 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6282 TmpInst.addOperand(Inst.getOperand(4));
6283 Inst = TmpInst;
6284 return true;
6285 }
6286
6287 case ARM::VLD4dWB_register_Asm_8:
6288 case ARM::VLD4dWB_register_Asm_16:
6289 case ARM::VLD4dWB_register_Asm_32:
6290 case ARM::VLD4qWB_register_Asm_8:
6291 case ARM::VLD4qWB_register_Asm_16:
6292 case ARM::VLD4qWB_register_Asm_32: {
6293 MCInst TmpInst;
6294 unsigned Spacing;
6295 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6296 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6297 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6298 Spacing));
6299 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6300 Spacing * 2));
6301 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6302 Spacing * 3));
6303 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6304 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6305 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6306 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6307 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6308 TmpInst.addOperand(Inst.getOperand(5));
6309 Inst = TmpInst;
6310 return true;
6311 }
6312
Jim Grosbachd7433e22012-01-23 23:45:44 +00006313 // VST3 multiple 3-element structure instructions.
6314 case ARM::VST3dAsm_8:
6315 case ARM::VST3dAsm_16:
6316 case ARM::VST3dAsm_32:
6317 case ARM::VST3qAsm_8:
6318 case ARM::VST3qAsm_16:
6319 case ARM::VST3qAsm_32: {
6320 MCInst TmpInst;
6321 unsigned Spacing;
6322 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6323 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6324 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6325 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6326 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6327 Spacing));
6328 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6329 Spacing * 2));
6330 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6331 TmpInst.addOperand(Inst.getOperand(4));
6332 Inst = TmpInst;
6333 return true;
6334 }
6335
6336 case ARM::VST3dWB_fixed_Asm_8:
6337 case ARM::VST3dWB_fixed_Asm_16:
6338 case ARM::VST3dWB_fixed_Asm_32:
6339 case ARM::VST3qWB_fixed_Asm_8:
6340 case ARM::VST3qWB_fixed_Asm_16:
6341 case ARM::VST3qWB_fixed_Asm_32: {
6342 MCInst TmpInst;
6343 unsigned Spacing;
6344 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6345 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6346 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6347 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6348 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6349 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6350 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6351 Spacing));
6352 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6353 Spacing * 2));
6354 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6355 TmpInst.addOperand(Inst.getOperand(4));
6356 Inst = TmpInst;
6357 return true;
6358 }
6359
6360 case ARM::VST3dWB_register_Asm_8:
6361 case ARM::VST3dWB_register_Asm_16:
6362 case ARM::VST3dWB_register_Asm_32:
6363 case ARM::VST3qWB_register_Asm_8:
6364 case ARM::VST3qWB_register_Asm_16:
6365 case ARM::VST3qWB_register_Asm_32: {
6366 MCInst TmpInst;
6367 unsigned Spacing;
6368 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6369 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6370 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6371 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6372 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6373 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6374 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6375 Spacing));
6376 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6377 Spacing * 2));
6378 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6379 TmpInst.addOperand(Inst.getOperand(5));
6380 Inst = TmpInst;
6381 return true;
6382 }
6383
Jim Grosbach539aab72012-01-24 00:58:13 +00006384 // VST4 multiple 3-element structure instructions.
6385 case ARM::VST4dAsm_8:
6386 case ARM::VST4dAsm_16:
6387 case ARM::VST4dAsm_32:
6388 case ARM::VST4qAsm_8:
6389 case ARM::VST4qAsm_16:
6390 case ARM::VST4qAsm_32: {
6391 MCInst TmpInst;
6392 unsigned Spacing;
6393 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6394 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6395 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6396 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6397 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6398 Spacing));
6399 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6400 Spacing * 2));
6401 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6402 Spacing * 3));
6403 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6404 TmpInst.addOperand(Inst.getOperand(4));
6405 Inst = TmpInst;
6406 return true;
6407 }
6408
6409 case ARM::VST4dWB_fixed_Asm_8:
6410 case ARM::VST4dWB_fixed_Asm_16:
6411 case ARM::VST4dWB_fixed_Asm_32:
6412 case ARM::VST4qWB_fixed_Asm_8:
6413 case ARM::VST4qWB_fixed_Asm_16:
6414 case ARM::VST4qWB_fixed_Asm_32: {
6415 MCInst TmpInst;
6416 unsigned Spacing;
6417 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6418 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6419 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6420 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6421 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6422 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6423 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6424 Spacing));
6425 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6426 Spacing * 2));
6427 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6428 Spacing * 3));
6429 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6430 TmpInst.addOperand(Inst.getOperand(4));
6431 Inst = TmpInst;
6432 return true;
6433 }
6434
6435 case ARM::VST4dWB_register_Asm_8:
6436 case ARM::VST4dWB_register_Asm_16:
6437 case ARM::VST4dWB_register_Asm_32:
6438 case ARM::VST4qWB_register_Asm_8:
6439 case ARM::VST4qWB_register_Asm_16:
6440 case ARM::VST4qWB_register_Asm_32: {
6441 MCInst TmpInst;
6442 unsigned Spacing;
6443 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6444 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6445 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6446 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6447 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6448 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6449 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6450 Spacing));
6451 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6452 Spacing * 2));
6453 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6454 Spacing * 3));
6455 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6456 TmpInst.addOperand(Inst.getOperand(5));
6457 Inst = TmpInst;
6458 return true;
6459 }
6460
Jim Grosbach863d2af2011-12-13 22:45:11 +00006461 // Handle the Thumb2 mode MOV complex aliases.
Jim Grosbach2cc5cda2011-12-21 20:54:00 +00006462 case ARM::t2MOVsr:
6463 case ARM::t2MOVSsr: {
6464 // Which instruction to expand to depends on the CCOut operand and
6465 // whether we're in an IT block if the register operands are low
6466 // registers.
6467 bool isNarrow = false;
6468 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6469 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6470 isARMLowRegister(Inst.getOperand(2).getReg()) &&
6471 Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
6472 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsr))
6473 isNarrow = true;
6474 MCInst TmpInst;
6475 unsigned newOpc;
6476 switch(ARM_AM::getSORegShOp(Inst.getOperand(3).getImm())) {
6477 default: llvm_unreachable("unexpected opcode!");
6478 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRrr : ARM::t2ASRrr; break;
6479 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRrr : ARM::t2LSRrr; break;
6480 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLrr : ARM::t2LSLrr; break;
6481 case ARM_AM::ror: newOpc = isNarrow ? ARM::tROR : ARM::t2RORrr; break;
6482 }
6483 TmpInst.setOpcode(newOpc);
6484 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6485 if (isNarrow)
6486 TmpInst.addOperand(MCOperand::CreateReg(
6487 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6488 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6489 TmpInst.addOperand(Inst.getOperand(2)); // Rm
6490 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6491 TmpInst.addOperand(Inst.getOperand(5));
6492 if (!isNarrow)
6493 TmpInst.addOperand(MCOperand::CreateReg(
6494 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6495 Inst = TmpInst;
6496 return true;
6497 }
Jim Grosbach863d2af2011-12-13 22:45:11 +00006498 case ARM::t2MOVsi:
6499 case ARM::t2MOVSsi: {
6500 // Which instruction to expand to depends on the CCOut operand and
6501 // whether we're in an IT block if the register operands are low
6502 // registers.
6503 bool isNarrow = false;
6504 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6505 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6506 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
6507 isNarrow = true;
6508 MCInst TmpInst;
6509 unsigned newOpc;
6510 switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
6511 default: llvm_unreachable("unexpected opcode!");
6512 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
6513 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
6514 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
6515 case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
Jim Grosbach520dc782011-12-21 21:04:19 +00006516 case ARM_AM::rrx: isNarrow = false; newOpc = ARM::t2RRX; break;
Jim Grosbach863d2af2011-12-13 22:45:11 +00006517 }
6518 unsigned Ammount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
6519 if (Ammount == 32) Ammount = 0;
6520 TmpInst.setOpcode(newOpc);
6521 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6522 if (isNarrow)
6523 TmpInst.addOperand(MCOperand::CreateReg(
6524 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6525 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbach520dc782011-12-21 21:04:19 +00006526 if (newOpc != ARM::t2RRX)
6527 TmpInst.addOperand(MCOperand::CreateImm(Ammount));
Jim Grosbach863d2af2011-12-13 22:45:11 +00006528 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6529 TmpInst.addOperand(Inst.getOperand(4));
6530 if (!isNarrow)
6531 TmpInst.addOperand(MCOperand::CreateReg(
6532 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6533 Inst = TmpInst;
6534 return true;
6535 }
6536 // Handle the ARM mode MOV complex aliases.
Jim Grosbach23f22072011-11-16 18:31:45 +00006537 case ARM::ASRr:
6538 case ARM::LSRr:
6539 case ARM::LSLr:
6540 case ARM::RORr: {
6541 ARM_AM::ShiftOpc ShiftTy;
6542 switch(Inst.getOpcode()) {
6543 default: llvm_unreachable("unexpected opcode!");
6544 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
6545 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
6546 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
6547 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
6548 }
Jim Grosbach23f22072011-11-16 18:31:45 +00006549 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
6550 MCInst TmpInst;
6551 TmpInst.setOpcode(ARM::MOVsr);
6552 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6553 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6554 TmpInst.addOperand(Inst.getOperand(2)); // Rm
6555 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6556 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6557 TmpInst.addOperand(Inst.getOperand(4));
6558 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6559 Inst = TmpInst;
6560 return true;
6561 }
Jim Grosbachee10ff82011-11-10 19:18:01 +00006562 case ARM::ASRi:
6563 case ARM::LSRi:
6564 case ARM::LSLi:
6565 case ARM::RORi: {
6566 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachee10ff82011-11-10 19:18:01 +00006567 switch(Inst.getOpcode()) {
6568 default: llvm_unreachable("unexpected opcode!");
6569 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
6570 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
6571 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
6572 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
6573 }
6574 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach48b368b2011-11-16 19:05:59 +00006575 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachee10ff82011-11-10 19:18:01 +00006576 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
6577 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach71810ab2011-11-10 16:44:55 +00006578 MCInst TmpInst;
Jim Grosbachee10ff82011-11-10 19:18:01 +00006579 TmpInst.setOpcode(Opc);
Jim Grosbach71810ab2011-11-10 16:44:55 +00006580 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6581 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachee10ff82011-11-10 19:18:01 +00006582 if (Opc == ARM::MOVsi)
6583 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach71810ab2011-11-10 16:44:55 +00006584 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6585 TmpInst.addOperand(Inst.getOperand(4));
6586 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6587 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006588 return true;
Jim Grosbach71810ab2011-11-10 16:44:55 +00006589 }
Jim Grosbach48b368b2011-11-16 19:05:59 +00006590 case ARM::RRXi: {
6591 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
6592 MCInst TmpInst;
6593 TmpInst.setOpcode(ARM::MOVsi);
6594 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6595 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6596 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6597 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6598 TmpInst.addOperand(Inst.getOperand(3));
6599 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
6600 Inst = TmpInst;
6601 return true;
6602 }
Jim Grosbach0352b462011-11-10 23:58:34 +00006603 case ARM::t2LDMIA_UPD: {
6604 // If this is a load of a single register, then we should use
6605 // a post-indexed LDR instruction instead, per the ARM ARM.
6606 if (Inst.getNumOperands() != 5)
6607 return false;
6608 MCInst TmpInst;
6609 TmpInst.setOpcode(ARM::t2LDR_POST);
6610 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6611 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6612 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6613 TmpInst.addOperand(MCOperand::CreateImm(4));
6614 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6615 TmpInst.addOperand(Inst.getOperand(3));
6616 Inst = TmpInst;
6617 return true;
6618 }
6619 case ARM::t2STMDB_UPD: {
6620 // If this is a store of a single register, then we should use
6621 // a pre-indexed STR instruction instead, per the ARM ARM.
6622 if (Inst.getNumOperands() != 5)
6623 return false;
6624 MCInst TmpInst;
6625 TmpInst.setOpcode(ARM::t2STR_PRE);
6626 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6627 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6628 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6629 TmpInst.addOperand(MCOperand::CreateImm(-4));
6630 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6631 TmpInst.addOperand(Inst.getOperand(3));
6632 Inst = TmpInst;
6633 return true;
6634 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00006635 case ARM::LDMIA_UPD:
6636 // If this is a load of a single register via a 'pop', then we should use
6637 // a post-indexed LDR instruction instead, per the ARM ARM.
6638 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
6639 Inst.getNumOperands() == 5) {
6640 MCInst TmpInst;
6641 TmpInst.setOpcode(ARM::LDR_POST_IMM);
6642 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6643 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6644 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6645 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
6646 TmpInst.addOperand(MCOperand::CreateImm(4));
6647 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6648 TmpInst.addOperand(Inst.getOperand(3));
6649 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006650 return true;
Jim Grosbachf8fce712011-08-11 17:35:48 +00006651 }
6652 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00006653 case ARM::STMDB_UPD:
6654 // If this is a store of a single register via a 'push', then we should use
6655 // a pre-indexed STR instruction instead, per the ARM ARM.
6656 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
6657 Inst.getNumOperands() == 5) {
6658 MCInst TmpInst;
6659 TmpInst.setOpcode(ARM::STR_PRE_IMM);
6660 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6661 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6662 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
6663 TmpInst.addOperand(MCOperand::CreateImm(-4));
6664 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6665 TmpInst.addOperand(Inst.getOperand(3));
6666 Inst = TmpInst;
6667 }
6668 break;
Jim Grosbachda847862011-12-05 21:06:26 +00006669 case ARM::t2ADDri12:
6670 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
6671 // mnemonic was used (not "addw"), encoding T3 is preferred.
6672 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
6673 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
6674 break;
6675 Inst.setOpcode(ARM::t2ADDri);
6676 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
6677 break;
6678 case ARM::t2SUBri12:
6679 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
6680 // mnemonic was used (not "subw"), encoding T3 is preferred.
6681 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
6682 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
6683 break;
6684 Inst.setOpcode(ARM::t2SUBri);
6685 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
6686 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006687 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00006688 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6689 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6690 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6691 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00006692 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006693 Inst.setOpcode(ARM::tADDi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006694 return true;
6695 }
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006696 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00006697 case ARM::tSUBi8:
6698 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6699 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6700 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6701 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00006702 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachf67e8552011-09-16 22:58:42 +00006703 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006704 return true;
6705 }
Jim Grosbachf67e8552011-09-16 22:58:42 +00006706 break;
Jim Grosbach927b9df2011-12-05 22:16:39 +00006707 case ARM::t2ADDrr: {
6708 // If the destination and first source operand are the same, and
6709 // there's no setting of the flags, use encoding T2 instead of T3.
6710 // Note that this is only for ADD, not SUB. This mirrors the system
6711 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
6712 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
6713 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbach713c7022011-12-05 22:27:04 +00006714 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6715 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbach927b9df2011-12-05 22:16:39 +00006716 break;
6717 MCInst TmpInst;
6718 TmpInst.setOpcode(ARM::tADDhirr);
6719 TmpInst.addOperand(Inst.getOperand(0));
6720 TmpInst.addOperand(Inst.getOperand(0));
6721 TmpInst.addOperand(Inst.getOperand(2));
6722 TmpInst.addOperand(Inst.getOperand(3));
6723 TmpInst.addOperand(Inst.getOperand(4));
6724 Inst = TmpInst;
6725 return true;
6726 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006727 case ARM::tB:
6728 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006729 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006730 Inst.setOpcode(ARM::tBcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006731 return true;
6732 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006733 break;
6734 case ARM::t2B:
6735 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006736 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006737 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006738 return true;
6739 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006740 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00006741 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00006742 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006743 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbachc0755102011-08-31 21:17:31 +00006744 Inst.setOpcode(ARM::t2B);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006745 return true;
6746 }
Jim Grosbachc0755102011-08-31 21:17:31 +00006747 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00006748 case ARM::tBcc:
6749 // If the conditional is AL, we really want tB.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006750 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbach395b4532011-08-17 22:57:40 +00006751 Inst.setOpcode(ARM::tB);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006752 return true;
6753 }
Jim Grosbach3ce23d32011-08-18 16:08:39 +00006754 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00006755 case ARM::tLDMIA: {
6756 // If the register list contains any high registers, or if the writeback
6757 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
6758 // instead if we're in Thumb2. Otherwise, this should have generated
6759 // an error in validateInstruction().
6760 unsigned Rn = Inst.getOperand(0).getReg();
6761 bool hasWritebackToken =
6762 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6763 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
6764 bool listContainsBase;
6765 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
6766 (!listContainsBase && !hasWritebackToken) ||
6767 (listContainsBase && hasWritebackToken)) {
6768 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6769 assert (isThumbTwo());
6770 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
6771 // If we're switching to the updating version, we need to insert
6772 // the writeback tied operand.
6773 if (hasWritebackToken)
6774 Inst.insert(Inst.begin(),
6775 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006776 return true;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00006777 }
6778 break;
6779 }
Jim Grosbach8213c962011-09-16 20:50:13 +00006780 case ARM::tSTMIA_UPD: {
6781 // If the register list contains any high registers, we need to use
6782 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6783 // should have generated an error in validateInstruction().
6784 unsigned Rn = Inst.getOperand(0).getReg();
6785 bool listContainsBase;
6786 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
6787 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6788 assert (isThumbTwo());
6789 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006790 return true;
Jim Grosbach8213c962011-09-16 20:50:13 +00006791 }
6792 break;
6793 }
Jim Grosbach54026372011-11-10 23:17:11 +00006794 case ARM::tPOP: {
6795 bool listContainsBase;
6796 // If the register list contains any high registers, we need to use
6797 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6798 // should have generated an error in validateInstruction().
6799 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00006800 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00006801 assert (isThumbTwo());
6802 Inst.setOpcode(ARM::t2LDMIA_UPD);
6803 // Add the base register and writeback operands.
6804 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6805 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006806 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00006807 }
6808 case ARM::tPUSH: {
6809 bool listContainsBase;
6810 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00006811 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00006812 assert (isThumbTwo());
6813 Inst.setOpcode(ARM::t2STMDB_UPD);
6814 // Add the base register and writeback operands.
6815 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6816 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006817 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00006818 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006819 case ARM::t2MOVi: {
6820 // If we can use the 16-bit encoding and the user didn't explicitly
6821 // request the 32-bit variant, transform it here.
6822 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6823 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00006824 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
6825 Inst.getOperand(4).getReg() == ARM::CPSR) ||
6826 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006827 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6828 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6829 // The operands aren't in the same order for tMOVi8...
6830 MCInst TmpInst;
6831 TmpInst.setOpcode(ARM::tMOVi8);
6832 TmpInst.addOperand(Inst.getOperand(0));
6833 TmpInst.addOperand(Inst.getOperand(4));
6834 TmpInst.addOperand(Inst.getOperand(1));
6835 TmpInst.addOperand(Inst.getOperand(2));
6836 TmpInst.addOperand(Inst.getOperand(3));
6837 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006838 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006839 }
6840 break;
6841 }
6842 case ARM::t2MOVr: {
6843 // If we can use the 16-bit encoding and the user didn't explicitly
6844 // request the 32-bit variant, transform it here.
6845 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6846 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6847 Inst.getOperand(2).getImm() == ARMCC::AL &&
6848 Inst.getOperand(4).getReg() == ARM::CPSR &&
6849 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6850 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6851 // The operands aren't the same for tMOV[S]r... (no cc_out)
6852 MCInst TmpInst;
6853 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
6854 TmpInst.addOperand(Inst.getOperand(0));
6855 TmpInst.addOperand(Inst.getOperand(1));
6856 TmpInst.addOperand(Inst.getOperand(2));
6857 TmpInst.addOperand(Inst.getOperand(3));
6858 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006859 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006860 }
6861 break;
6862 }
Jim Grosbach326efe52011-09-19 20:29:33 +00006863 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00006864 case ARM::t2SXTB:
6865 case ARM::t2UXTH:
6866 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00006867 // If we can use the 16-bit encoding and the user didn't explicitly
6868 // request the 32-bit variant, transform it here.
6869 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6870 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6871 Inst.getOperand(2).getImm() == 0 &&
6872 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6873 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00006874 unsigned NewOpc;
6875 switch (Inst.getOpcode()) {
6876 default: llvm_unreachable("Illegal opcode!");
6877 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
6878 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
6879 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
6880 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
6881 }
Jim Grosbach326efe52011-09-19 20:29:33 +00006882 // The operands aren't the same for thumb1 (no rotate operand).
6883 MCInst TmpInst;
6884 TmpInst.setOpcode(NewOpc);
6885 TmpInst.addOperand(Inst.getOperand(0));
6886 TmpInst.addOperand(Inst.getOperand(1));
6887 TmpInst.addOperand(Inst.getOperand(3));
6888 TmpInst.addOperand(Inst.getOperand(4));
6889 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006890 return true;
Jim Grosbach326efe52011-09-19 20:29:33 +00006891 }
6892 break;
6893 }
Jim Grosbach04b5d932011-12-20 00:59:38 +00006894 case ARM::MOVsi: {
6895 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm());
6896 if (SOpc == ARM_AM::rrx) return false;
6897 if (ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()) == 0) {
6898 // Shifting by zero is accepted as a vanilla 'MOVr'
6899 MCInst TmpInst;
6900 TmpInst.setOpcode(ARM::MOVr);
6901 TmpInst.addOperand(Inst.getOperand(0));
6902 TmpInst.addOperand(Inst.getOperand(1));
6903 TmpInst.addOperand(Inst.getOperand(3));
6904 TmpInst.addOperand(Inst.getOperand(4));
6905 TmpInst.addOperand(Inst.getOperand(5));
6906 Inst = TmpInst;
6907 return true;
6908 }
6909 return false;
6910 }
Jim Grosbach8d9550b2011-12-22 18:04:04 +00006911 case ARM::ANDrsi:
6912 case ARM::ORRrsi:
6913 case ARM::EORrsi:
6914 case ARM::BICrsi:
6915 case ARM::SUBrsi:
6916 case ARM::ADDrsi: {
6917 unsigned newOpc;
6918 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(3).getImm());
6919 if (SOpc == ARM_AM::rrx) return false;
6920 switch (Inst.getOpcode()) {
Matt Beaumont-Gay19055cc2012-01-03 19:03:59 +00006921 default: assert(0 && "unexpected opcode!");
Jim Grosbach8d9550b2011-12-22 18:04:04 +00006922 case ARM::ANDrsi: newOpc = ARM::ANDrr; break;
6923 case ARM::ORRrsi: newOpc = ARM::ORRrr; break;
6924 case ARM::EORrsi: newOpc = ARM::EORrr; break;
6925 case ARM::BICrsi: newOpc = ARM::BICrr; break;
6926 case ARM::SUBrsi: newOpc = ARM::SUBrr; break;
6927 case ARM::ADDrsi: newOpc = ARM::ADDrr; break;
6928 }
6929 // If the shift is by zero, use the non-shifted instruction definition.
6930 if (ARM_AM::getSORegOffset(Inst.getOperand(3).getImm()) == 0) {
6931 MCInst TmpInst;
6932 TmpInst.setOpcode(newOpc);
6933 TmpInst.addOperand(Inst.getOperand(0));
6934 TmpInst.addOperand(Inst.getOperand(1));
6935 TmpInst.addOperand(Inst.getOperand(2));
6936 TmpInst.addOperand(Inst.getOperand(4));
6937 TmpInst.addOperand(Inst.getOperand(5));
6938 TmpInst.addOperand(Inst.getOperand(6));
6939 Inst = TmpInst;
6940 return true;
6941 }
6942 return false;
6943 }
Jim Grosbach89df9962011-08-26 21:43:41 +00006944 case ARM::t2IT: {
6945 // The mask bits for all but the first condition are represented as
6946 // the low bit of the condition code value implies 't'. We currently
6947 // always have 1 implies 't', so XOR toggle the bits if the low bit
6948 // of the condition code is zero. The encoding also expects the low
6949 // bit of the condition to be encoded as bit 4 of the mask operand,
6950 // so mask that in if needed
6951 MCOperand &MO = Inst.getOperand(1);
6952 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006953 unsigned OrigMask = Mask;
6954 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00006955 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00006956 assert(Mask && TZ <= 3 && "illegal IT mask value!");
6957 for (unsigned i = 3; i != TZ; --i)
6958 Mask ^= 1 << i;
6959 } else
6960 Mask |= 0x10;
6961 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006962
6963 // Set up the IT block state according to the IT instruction we just
6964 // matched.
6965 assert(!inITBlock() && "nested IT blocks?!");
6966 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
6967 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
6968 ITState.CurPosition = 0;
6969 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00006970 break;
6971 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00006972 }
Jim Grosbach83ec8772011-11-10 23:42:14 +00006973 return false;
Jim Grosbachf8fce712011-08-11 17:35:48 +00006974}
6975
Jim Grosbach47a0d522011-08-16 20:45:50 +00006976unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
6977 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
6978 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00006979 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00006980 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00006981 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
6982 assert(MCID.hasOptionalDef() &&
6983 "optionally flag setting instruction missing optional def operand");
6984 assert(MCID.NumOperands == Inst.getNumOperands() &&
6985 "operand count mismatch!");
6986 // Find the optional-def operand (cc_out).
6987 unsigned OpNo;
6988 for (OpNo = 0;
6989 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
6990 ++OpNo)
6991 ;
6992 // If we're parsing Thumb1, reject it completely.
6993 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
6994 return Match_MnemonicFail;
6995 // If we're parsing Thumb2, which form is legal depends on whether we're
6996 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006997 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
6998 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00006999 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007000 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
7001 inITBlock())
7002 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00007003 }
Jim Grosbach194bd892011-08-16 22:20:01 +00007004 // Some high-register supporting Thumb1 encodings only allow both registers
7005 // to be from r0-r7 when in Thumb2.
7006 else if (Opc == ARM::tADDhirr && isThumbOne() &&
7007 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7008 isARMLowRegister(Inst.getOperand(2).getReg()))
7009 return Match_RequiresThumb2;
7010 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00007011 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00007012 isARMLowRegister(Inst.getOperand(0).getReg()) &&
7013 isARMLowRegister(Inst.getOperand(1).getReg()))
7014 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00007015 return Match_Success;
7016}
7017
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007018bool ARMAsmParser::
7019MatchAndEmitInstruction(SMLoc IDLoc,
7020 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
7021 MCStreamer &Out) {
7022 MCInst Inst;
7023 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00007024 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00007025 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00007026 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00007027 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00007028 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00007029 // Context sensitive operand constraints aren't handled by the matcher,
7030 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00007031 if (validateInstruction(Inst, Operands)) {
7032 // Still progress the IT block, otherwise one wrong condition causes
7033 // nasty cascading errors.
7034 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00007035 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00007036 }
Jim Grosbach189610f2011-07-26 18:25:39 +00007037
Jim Grosbachf8fce712011-08-11 17:35:48 +00007038 // Some instructions need post-processing to, for example, tweak which
Jim Grosbach83ec8772011-11-10 23:42:14 +00007039 // encoding is selected. Loop on it while changes happen so the
7040 // individual transformations can chain off each other. E.g.,
7041 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
7042 while (processInstruction(Inst, Operands))
7043 ;
Jim Grosbachf8fce712011-08-11 17:35:48 +00007044
Jim Grosbacha1109882011-09-02 23:22:08 +00007045 // Only move forward at the very end so that everything in validate
7046 // and process gets a consistent answer about whether we're in an IT
7047 // block.
7048 forwardITPosition();
7049
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007050 Out.EmitInstruction(Inst);
7051 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00007052 case Match_MissingFeature:
7053 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
7054 return true;
7055 case Match_InvalidOperand: {
7056 SMLoc ErrorLoc = IDLoc;
7057 if (ErrorInfo != ~0U) {
7058 if (ErrorInfo >= Operands.size())
7059 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00007060
Chris Lattnere73d4f82010-10-28 21:41:58 +00007061 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
7062 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
7063 }
Jim Grosbach16c74252010-10-29 14:46:02 +00007064
Chris Lattnere73d4f82010-10-28 21:41:58 +00007065 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007066 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00007067 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00007068 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00007069 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00007070 // The converter function will have already emited a diagnostic.
7071 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007072 case Match_RequiresNotITBlock:
7073 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00007074 case Match_RequiresITBlock:
7075 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00007076 case Match_RequiresV6:
7077 return Error(IDLoc, "instruction variant requires ARMv6 or later");
7078 case Match_RequiresThumb2:
7079 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00007080 }
Jim Grosbach16c74252010-10-29 14:46:02 +00007081
Eric Christopherc223e2b2010-10-29 09:26:59 +00007082 llvm_unreachable("Implement any new match types added!");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007083}
7084
Jim Grosbach1355cf12011-07-26 17:10:22 +00007085/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007086bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
7087 StringRef IDVal = DirectiveID.getIdentifier();
7088 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007089 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007090 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007091 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach9a70df92011-12-07 18:04:19 +00007092 else if (IDVal == ".arm")
7093 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007094 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007095 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007096 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007097 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007098 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007099 return parseDirectiveSyntax(DirectiveID.getLoc());
Jim Grosbacha39cda72011-12-14 02:16:11 +00007100 else if (IDVal == ".unreq")
7101 return parseDirectiveUnreq(DirectiveID.getLoc());
Jason W Kimd7c9e082011-12-20 17:38:12 +00007102 else if (IDVal == ".arch")
7103 return parseDirectiveArch(DirectiveID.getLoc());
7104 else if (IDVal == ".eabi_attribute")
7105 return parseDirectiveEabiAttr(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007106 return true;
7107}
7108
Jim Grosbach1355cf12011-07-26 17:10:22 +00007109/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007110/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00007111bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007112 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7113 for (;;) {
7114 const MCExpr *Value;
7115 if (getParser().ParseExpression(Value))
7116 return true;
7117
Chris Lattneraaec2052010-01-19 19:46:13 +00007118 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007119
7120 if (getLexer().is(AsmToken::EndOfStatement))
7121 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00007122
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007123 // FIXME: Improve diagnostic.
7124 if (getLexer().isNot(AsmToken::Comma))
7125 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007126 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007127 }
7128 }
7129
Sean Callananb9a25b72010-01-19 20:27:46 +00007130 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007131 return false;
7132}
7133
Jim Grosbach1355cf12011-07-26 17:10:22 +00007134/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00007135/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00007136bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00007137 if (getLexer().isNot(AsmToken::EndOfStatement))
7138 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007139 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007140
Jim Grosbach9a70df92011-12-07 18:04:19 +00007141 if (!isThumb())
7142 SwitchMode();
7143 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
7144 return false;
7145}
7146
7147/// parseDirectiveARM
7148/// ::= .arm
7149bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
7150 if (getLexer().isNot(AsmToken::EndOfStatement))
7151 return Error(L, "unexpected token in directive");
7152 Parser.Lex();
7153
7154 if (isThumb())
7155 SwitchMode();
7156 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby515d5092009-10-15 20:48:48 +00007157 return false;
7158}
7159
Jim Grosbach1355cf12011-07-26 17:10:22 +00007160/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00007161/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00007162bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00007163 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
7164 bool isMachO = MAI.hasSubsectionsViaSymbols();
7165 StringRef Name;
Jim Grosbachde4d8392011-12-21 22:30:16 +00007166 bool needFuncName = true;
Rafael Espindola64695402011-05-16 16:17:21 +00007167
Jim Grosbachde4d8392011-12-21 22:30:16 +00007168 // Darwin asm has (optionally) function name after .thumb_func direction
Rafael Espindola64695402011-05-16 16:17:21 +00007169 // ELF doesn't
7170 if (isMachO) {
7171 const AsmToken &Tok = Parser.getTok();
Jim Grosbachde4d8392011-12-21 22:30:16 +00007172 if (Tok.isNot(AsmToken::EndOfStatement)) {
7173 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
7174 return Error(L, "unexpected token in .thumb_func directive");
7175 Name = Tok.getIdentifier();
7176 Parser.Lex(); // Consume the identifier token.
7177 needFuncName = false;
7178 }
Rafael Espindola64695402011-05-16 16:17:21 +00007179 }
7180
Jim Grosbachde4d8392011-12-21 22:30:16 +00007181 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby515d5092009-10-15 20:48:48 +00007182 return Error(L, "unexpected token in directive");
Jim Grosbachde4d8392011-12-21 22:30:16 +00007183
7184 // Eat the end of statement and any blank lines that follow.
7185 while (getLexer().is(AsmToken::EndOfStatement))
7186 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007187
Rafael Espindola64695402011-05-16 16:17:21 +00007188 // FIXME: assuming function name will be the line following .thumb_func
Jim Grosbachde4d8392011-12-21 22:30:16 +00007189 // We really should be checking the next symbol definition even if there's
7190 // stuff in between.
7191 if (needFuncName) {
Jim Grosbachd475f862011-11-10 20:48:53 +00007192 Name = Parser.getTok().getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00007193 }
7194
Jim Grosbach642fc9c2010-11-05 22:33:53 +00007195 // Mark symbol as a thumb symbol.
7196 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
7197 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00007198 return false;
7199}
7200
Jim Grosbach1355cf12011-07-26 17:10:22 +00007201/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00007202/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00007203bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00007204 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00007205 if (Tok.isNot(AsmToken::Identifier))
7206 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00007207 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00007208 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00007209 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00007210 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00007211 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00007212 else
7213 return Error(L, "unrecognized syntax mode in .syntax directive");
7214
7215 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00007216 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007217 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007218
7219 // TODO tell the MC streamer the mode
7220 // getParser().getStreamer().Emit???();
7221 return false;
7222}
7223
Jim Grosbach1355cf12011-07-26 17:10:22 +00007224/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00007225/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00007226bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00007227 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00007228 if (Tok.isNot(AsmToken::Integer))
7229 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00007230 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00007231 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00007232 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00007233 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00007234 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007235 else
7236 return Error(L, "invalid operand to .code directive");
7237
7238 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00007239 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007240 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007241
Evan Cheng32869202011-07-08 22:36:29 +00007242 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00007243 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00007244 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00007245 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00007246 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00007247 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00007248 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00007249 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00007250 }
Jim Grosbach2a301702010-11-05 22:40:53 +00007251
Kevin Enderby515d5092009-10-15 20:48:48 +00007252 return false;
7253}
7254
Jim Grosbacha39cda72011-12-14 02:16:11 +00007255/// parseDirectiveReq
7256/// ::= name .req registername
7257bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
7258 Parser.Lex(); // Eat the '.req' token.
7259 unsigned Reg;
7260 SMLoc SRegLoc, ERegLoc;
7261 if (ParseRegister(Reg, SRegLoc, ERegLoc)) {
7262 Parser.EatToEndOfStatement();
7263 return Error(SRegLoc, "register name expected");
7264 }
7265
7266 // Shouldn't be anything else.
7267 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
7268 Parser.EatToEndOfStatement();
7269 return Error(Parser.getTok().getLoc(),
7270 "unexpected input in .req directive.");
7271 }
7272
7273 Parser.Lex(); // Consume the EndOfStatement
7274
7275 if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg)
7276 return Error(SRegLoc, "redefinition of '" + Name +
7277 "' does not match original.");
7278
7279 return false;
7280}
7281
7282/// parseDirectiveUneq
7283/// ::= .unreq registername
7284bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
7285 if (Parser.getTok().isNot(AsmToken::Identifier)) {
7286 Parser.EatToEndOfStatement();
7287 return Error(L, "unexpected input in .unreq directive.");
7288 }
7289 RegisterReqs.erase(Parser.getTok().getIdentifier());
7290 Parser.Lex(); // Eat the identifier.
7291 return false;
7292}
7293
Jason W Kimd7c9e082011-12-20 17:38:12 +00007294/// parseDirectiveArch
7295/// ::= .arch token
7296bool ARMAsmParser::parseDirectiveArch(SMLoc L) {
7297 return true;
7298}
7299
7300/// parseDirectiveEabiAttr
7301/// ::= .eabi_attribute int, int
7302bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
7303 return true;
7304}
7305
Sean Callanan90b70972010-04-07 20:29:34 +00007306extern "C" void LLVMInitializeARMAsmLexer();
7307
Kevin Enderby9c41fa82009-10-30 22:55:57 +00007308/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007309extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00007310 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
7311 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00007312 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007313}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00007314
Chris Lattner0692ee62010-09-06 19:11:01 +00007315#define GET_REGISTER_MATCHER
7316#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00007317#include "ARMGenAsmMatcher.inc"