blob: 88659796705dcfd4b6be6450e28519fd404d593e [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;
Jim Grosbach28f08c92012-03-05 19:33:30 +000047 const MCRegisterInfo *MRI;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000048
Jim Grosbacha39cda72011-12-14 02:16:11 +000049 // Map of register aliases registers via the .req directive.
50 StringMap<unsigned> RegisterReqs;
51
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000052 struct {
53 ARMCC::CondCodes Cond; // Condition for IT block.
54 unsigned Mask:4; // Condition mask for instructions.
55 // Starting at first 1 (from lsb).
56 // '1' condition as indicated in IT.
57 // '0' inverse of condition (else).
58 // Count of instructions in IT block is
59 // 4 - trailingzeroes(mask)
60
61 bool FirstCond; // Explicit flag for when we're parsing the
62 // First instruction in the IT block. It's
63 // implied in the mask, so needs special
64 // handling.
65
66 unsigned CurPosition; // Current position in parsing of IT
67 // block. In range [0,3]. Initialized
68 // according to count of instructions in block.
69 // ~0U if no active IT block.
70 } ITState;
71 bool inITBlock() { return ITState.CurPosition != ~0U;}
Jim Grosbacha1109882011-09-02 23:22:08 +000072 void forwardITPosition() {
73 if (!inITBlock()) return;
74 // Move to the next instruction in the IT block, if there is one. If not,
75 // mark the block as done.
76 unsigned TZ = CountTrailingZeros_32(ITState.Mask);
77 if (++ITState.CurPosition == 5 - TZ)
78 ITState.CurPosition = ~0U; // Done with the IT block after this.
79 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000080
81
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000082 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000083 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
84
Benjamin Kramer362a05a2012-04-15 17:04:27 +000085 bool Warning(SMLoc L, const Twine &Msg,
86 ArrayRef<SMRange> Ranges = ArrayRef<SMRange>()) {
87 return Parser.Warning(L, Msg, Ranges);
88 }
89 bool Error(SMLoc L, const Twine &Msg,
90 ArrayRef<SMRange> Ranges = ArrayRef<SMRange>()) {
91 return Parser.Error(L, Msg, Ranges);
92 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000093
Jim Grosbach1355cf12011-07-26 17:10:22 +000094 int tryParseRegister();
95 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d87ec22011-07-26 20:41:24 +000096 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000097 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +000098 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000099 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
100 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000101 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
102 unsigned &ShiftAmount);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000103 bool parseDirectiveWord(unsigned Size, SMLoc L);
104 bool parseDirectiveThumb(SMLoc L);
Jim Grosbach9a70df92011-12-07 18:04:19 +0000105 bool parseDirectiveARM(SMLoc L);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000106 bool parseDirectiveThumbFunc(SMLoc L);
107 bool parseDirectiveCode(SMLoc L);
108 bool parseDirectiveSyntax(SMLoc L);
Jim Grosbacha39cda72011-12-14 02:16:11 +0000109 bool parseDirectiveReq(StringRef Name, SMLoc L);
110 bool parseDirectiveUnreq(SMLoc L);
Jason W Kimd7c9e082011-12-20 17:38:12 +0000111 bool parseDirectiveArch(SMLoc L);
112 bool parseDirectiveEabiAttr(SMLoc L);
Kevin Enderby515d5092009-10-15 20:48:48 +0000113
Jim Grosbach1355cf12011-07-26 17:10:22 +0000114 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach89df9962011-08-26 21:43:41 +0000115 bool &CarrySetting, unsigned &ProcessorIMod,
116 StringRef &ITMask);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000117 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +0000118 bool &CanAcceptPredicationCode);
Jim Grosbach16c74252010-10-29 14:46:02 +0000119
Evan Chengebdeeab2011-07-08 01:53:10 +0000120 bool isThumb() const {
121 // FIXME: Can tablegen auto-generate this?
Evan Chengffc0e732011-07-09 05:47:46 +0000122 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000123 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000124 bool isThumbOne() const {
Evan Chengffc0e732011-07-09 05:47:46 +0000125 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000126 }
Jim Grosbach47a0d522011-08-16 20:45:50 +0000127 bool isThumbTwo() const {
128 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
129 }
Jim Grosbach194bd892011-08-16 22:20:01 +0000130 bool hasV6Ops() const {
131 return STI.getFeatureBits() & ARM::HasV6Ops;
132 }
James Molloyacad68d2011-09-28 14:21:38 +0000133 bool hasV7Ops() const {
134 return STI.getFeatureBits() & ARM::HasV7Ops;
135 }
Evan Cheng32869202011-07-08 22:36:29 +0000136 void SwitchMode() {
Evan Chengffc0e732011-07-09 05:47:46 +0000137 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
138 setAvailableFeatures(FB);
Evan Cheng32869202011-07-08 22:36:29 +0000139 }
James Molloyacad68d2011-09-28 14:21:38 +0000140 bool isMClass() const {
141 return STI.getFeatureBits() & ARM::FeatureMClass;
142 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000143
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000144 /// @name Auto-generated Match Functions
145 /// {
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000146
Chris Lattner0692ee62010-09-06 19:11:01 +0000147#define GET_ASSEMBLER_HEADER
148#include "ARMGenAsmMatcher.inc"
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000149
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000150 /// }
151
Jim Grosbach89df9962011-08-26 21:43:41 +0000152 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000153 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000154 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000155 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000156 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000157 OperandMatchResultTy parseCoprocOptionOperand(
158 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000159 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000160 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000161 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000162 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000163 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000164 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachf6c05252011-07-21 17:23:04 +0000165 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
166 StringRef Op, int Low, int High);
167 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
168 return parsePKHImm(O, "lsl", 0, 31);
169 }
170 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
171 return parsePKHImm(O, "asr", 1, 32);
172 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000173 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach580f4a92011-07-25 22:20:28 +0000174 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000175 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000176 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000177 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach251bf252011-08-10 21:56:18 +0000178 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9d390362011-10-03 23:38:36 +0000179 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach862019c2011-10-18 23:02:30 +0000180 OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7636bf62011-12-02 00:35:16 +0000181 OperandMatchResultTy parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000182
183 // Asm Match Converter Methods
Jim Grosbacha77295d2011-09-08 22:07:06 +0000184 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
185 const SmallVectorImpl<MCParsedAsmOperand*> &);
186 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
187 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheeec0252011-09-08 00:39:19 +0000188 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
189 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachee2c2a42011-09-16 21:55:56 +0000190 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
191 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000192 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000193 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson9ab0f252011-08-26 20:43:14 +0000194 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
195 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach548340c2011-08-11 19:22:40 +0000196 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
197 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000198 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000199 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7b8f46c2011-08-11 21:17:22 +0000200 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
201 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000202 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
203 const SmallVectorImpl<MCParsedAsmOperand*> &);
204 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
205 const SmallVectorImpl<MCParsedAsmOperand*> &);
206 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
207 const SmallVectorImpl<MCParsedAsmOperand*> &);
208 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
209 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000210 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
211 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach14605d12011-08-11 20:28:23 +0000212 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
213 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach623a4542011-08-10 22:42:16 +0000214 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
215 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach88ae2bc2011-08-19 22:07:46 +0000216 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
217 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach12431322011-10-24 22:16:58 +0000218 bool cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
219 const SmallVectorImpl<MCParsedAsmOperand*> &);
220 bool cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
221 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach4334e032011-10-31 21:50:31 +0000222 bool cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
223 const SmallVectorImpl<MCParsedAsmOperand*> &);
224 bool cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
225 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach189610f2011-07-26 18:25:39 +0000226
227 bool validateInstruction(MCInst &Inst,
228 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach83ec8772011-11-10 23:42:14 +0000229 bool processInstruction(MCInst &Inst,
Jim Grosbachf8fce712011-08-11 17:35:48 +0000230 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachd54b4e62011-08-16 21:12:37 +0000231 bool shouldOmitCCOutOperand(StringRef Mnemonic,
232 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach189610f2011-07-26 18:25:39 +0000233
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000234public:
Jim Grosbach47a0d522011-08-16 20:45:50 +0000235 enum ARMMatchResultTy {
Jim Grosbach194bd892011-08-16 22:20:01 +0000236 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000237 Match_RequiresNotITBlock,
Jim Grosbach194bd892011-08-16 22:20:01 +0000238 Match_RequiresV6,
239 Match_RequiresThumb2
Jim Grosbach47a0d522011-08-16 20:45:50 +0000240 };
241
Evan Chengffc0e732011-07-09 05:47:46 +0000242 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng94b95502011-07-26 00:24:13 +0000243 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Chengebdeeab2011-07-08 01:53:10 +0000244 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng32869202011-07-08 22:36:29 +0000245
Jim Grosbach28f08c92012-03-05 19:33:30 +0000246 // Cache the MCRegisterInfo.
247 MRI = &getContext().getRegisterInfo();
248
Evan Chengebdeeab2011-07-08 01:53:10 +0000249 // Initialize the set of available features.
Evan Chengffc0e732011-07-09 05:47:46 +0000250 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000251
252 // Not in an ITBlock to start with.
253 ITState.CurPosition = ~0U;
Evan Chengebdeeab2011-07-08 01:53:10 +0000254 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000255
Jim Grosbach1355cf12011-07-26 17:10:22 +0000256 // Implementation of the MCTargetAsmParser interface:
257 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
258 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbach189610f2011-07-26 18:25:39 +0000259 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000260 bool ParseDirective(AsmToken DirectiveID);
261
Jim Grosbach47a0d522011-08-16 20:45:50 +0000262 unsigned checkTargetMatchPredicate(MCInst &Inst);
263
Jim Grosbach1355cf12011-07-26 17:10:22 +0000264 bool MatchAndEmitInstruction(SMLoc IDLoc,
265 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
266 MCStreamer &Out);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000267};
Jim Grosbach16c74252010-10-29 14:46:02 +0000268} // end anonymous namespace
269
Chris Lattner3a697562010-10-28 17:20:03 +0000270namespace {
271
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000272/// ARMOperand - Instances of this class represent a parsed ARM machine
273/// instruction.
Bill Wendling146018f2010-11-06 21:42:12 +0000274class ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000275 enum KindTy {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000276 k_CondCode,
277 k_CCOut,
278 k_ITCondMask,
279 k_CoprocNum,
280 k_CoprocReg,
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000281 k_CoprocOption,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000282 k_Immediate,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000283 k_MemBarrierOpt,
284 k_Memory,
285 k_PostIndexRegister,
286 k_MSRMask,
287 k_ProcIFlags,
Jim Grosbach460a9052011-10-07 23:56:00 +0000288 k_VectorIndex,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000289 k_Register,
290 k_RegisterList,
291 k_DPRRegisterList,
292 k_SPRRegisterList,
Jim Grosbach862019c2011-10-18 23:02:30 +0000293 k_VectorList,
Jim Grosbach98b05a52011-11-30 01:09:44 +0000294 k_VectorListAllLanes,
Jim Grosbach7636bf62011-12-02 00:35:16 +0000295 k_VectorListIndexed,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000296 k_ShiftedRegister,
297 k_ShiftedImmediate,
298 k_ShifterImmediate,
299 k_RotateImmediate,
300 k_BitfieldDescriptor,
301 k_Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000302 } Kind;
303
Sean Callanan76264762010-04-02 22:27:05 +0000304 SMLoc StartLoc, EndLoc;
Bill Wendling24d22d22010-11-18 21:50:54 +0000305 SmallVector<unsigned, 8> Registers;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000306
307 union {
308 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000309 ARMCC::CondCodes Val;
310 } CC;
311
312 struct {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000313 unsigned Val;
314 } Cop;
315
316 struct {
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000317 unsigned Val;
318 } CoprocOption;
319
320 struct {
Jim Grosbach89df9962011-08-26 21:43:41 +0000321 unsigned Mask:4;
322 } ITMask;
323
324 struct {
325 ARM_MB::MemBOpt Val;
326 } MBOpt;
327
328 struct {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000329 ARM_PROC::IFlags Val;
330 } IFlags;
331
332 struct {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000333 unsigned Val;
334 } MMask;
335
336 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000337 const char *Data;
338 unsigned Length;
339 } Tok;
340
341 struct {
342 unsigned RegNum;
343 } Reg;
344
Jim Grosbach862019c2011-10-18 23:02:30 +0000345 // A vector register list is a sequential list of 1 to 4 registers.
346 struct {
347 unsigned RegNum;
348 unsigned Count;
Jim Grosbach7636bf62011-12-02 00:35:16 +0000349 unsigned LaneIndex;
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +0000350 bool isDoubleSpaced;
Jim Grosbach862019c2011-10-18 23:02:30 +0000351 } VectorList;
352
Bill Wendling8155e5b2010-11-06 22:19:43 +0000353 struct {
Jim Grosbach460a9052011-10-07 23:56:00 +0000354 unsigned Val;
355 } VectorIndex;
356
357 struct {
Kevin Enderbycfe07242009-10-13 22:19:02 +0000358 const MCExpr *Val;
359 } Imm;
Jim Grosbach16c74252010-10-29 14:46:02 +0000360
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +0000361 /// Combined record for all forms of ARM address expressions.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000362 struct {
363 unsigned BaseRegNum;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000364 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
365 // was specified.
366 const MCConstantExpr *OffsetImm; // Offset immediate value
367 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
368 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbach57dcb852011-10-11 17:29:55 +0000369 unsigned ShiftImm; // shift for OffsetReg.
370 unsigned Alignment; // 0 = no alignment specified
Jim Grosbacheeaf1c12011-12-19 18:31:43 +0000371 // n = alignment in bytes (2, 4, 8, 16, or 32)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000372 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbache53c87b2011-10-11 15:59:20 +0000373 } Memory;
Owen Anderson00828302011-03-18 22:50:18 +0000374
375 struct {
Jim Grosbach7ce05792011-08-03 23:50:40 +0000376 unsigned RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000377 bool isAdd;
378 ARM_AM::ShiftOpc ShiftTy;
379 unsigned ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000380 } PostIdxReg;
381
382 struct {
Jim Grosbach580f4a92011-07-25 22:20:28 +0000383 bool isASR;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000384 unsigned Imm;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000385 } ShifterImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000386 struct {
387 ARM_AM::ShiftOpc ShiftTy;
388 unsigned SrcReg;
389 unsigned ShiftReg;
390 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000391 } RegShiftedReg;
Owen Anderson92a20222011-07-21 18:54:16 +0000392 struct {
393 ARM_AM::ShiftOpc ShiftTy;
394 unsigned SrcReg;
395 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000396 } RegShiftedImm;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000397 struct {
398 unsigned Imm;
399 } RotImm;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000400 struct {
401 unsigned LSB;
402 unsigned Width;
403 } Bitfield;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000404 };
Jim Grosbach16c74252010-10-29 14:46:02 +0000405
Bill Wendling146018f2010-11-06 21:42:12 +0000406 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
407public:
Sean Callanan76264762010-04-02 22:27:05 +0000408 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
409 Kind = o.Kind;
410 StartLoc = o.StartLoc;
411 EndLoc = o.EndLoc;
412 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000413 case k_CondCode:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000414 CC = o.CC;
415 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000416 case k_ITCondMask:
Jim Grosbach89df9962011-08-26 21:43:41 +0000417 ITMask = o.ITMask;
418 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000419 case k_Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000420 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000421 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000422 case k_CCOut:
423 case k_Register:
Sean Callanan76264762010-04-02 22:27:05 +0000424 Reg = o.Reg;
425 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000426 case k_RegisterList:
427 case k_DPRRegisterList:
428 case k_SPRRegisterList:
Bill Wendling24d22d22010-11-18 21:50:54 +0000429 Registers = o.Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000430 break;
Jim Grosbach862019c2011-10-18 23:02:30 +0000431 case k_VectorList:
Jim Grosbach98b05a52011-11-30 01:09:44 +0000432 case k_VectorListAllLanes:
Jim Grosbach7636bf62011-12-02 00:35:16 +0000433 case k_VectorListIndexed:
Jim Grosbach862019c2011-10-18 23:02:30 +0000434 VectorList = o.VectorList;
435 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000436 case k_CoprocNum:
437 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000438 Cop = o.Cop;
439 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000440 case k_CoprocOption:
441 CoprocOption = o.CoprocOption;
442 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000443 case k_Immediate:
Sean Callanan76264762010-04-02 22:27:05 +0000444 Imm = o.Imm;
445 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000446 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000447 MBOpt = o.MBOpt;
448 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000449 case k_Memory:
Jim Grosbache53c87b2011-10-11 15:59:20 +0000450 Memory = o.Memory;
Sean Callanan76264762010-04-02 22:27:05 +0000451 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000452 case k_PostIndexRegister:
Jim Grosbach7ce05792011-08-03 23:50:40 +0000453 PostIdxReg = o.PostIdxReg;
454 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000455 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000456 MMask = o.MMask;
457 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000458 case k_ProcIFlags:
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000459 IFlags = o.IFlags;
Owen Anderson00828302011-03-18 22:50:18 +0000460 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000461 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +0000462 ShifterImm = o.ShifterImm;
Owen Anderson00828302011-03-18 22:50:18 +0000463 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000464 case k_ShiftedRegister:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000465 RegShiftedReg = o.RegShiftedReg;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000466 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000467 case k_ShiftedImmediate:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000468 RegShiftedImm = o.RegShiftedImm;
Owen Anderson92a20222011-07-21 18:54:16 +0000469 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000470 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000471 RotImm = o.RotImm;
472 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000473 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000474 Bitfield = o.Bitfield;
475 break;
Jim Grosbach460a9052011-10-07 23:56:00 +0000476 case k_VectorIndex:
477 VectorIndex = o.VectorIndex;
478 break;
Sean Callanan76264762010-04-02 22:27:05 +0000479 }
480 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000481
Sean Callanan76264762010-04-02 22:27:05 +0000482 /// getStartLoc - Get the location of the first token of this operand.
483 SMLoc getStartLoc() const { return StartLoc; }
484 /// getEndLoc - Get the location of the last token of this operand.
485 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000486
Benjamin Kramer362a05a2012-04-15 17:04:27 +0000487 SMRange getLocRange() const { return SMRange(StartLoc, EndLoc); }
488
Daniel Dunbar8462b302010-08-11 06:36:53 +0000489 ARMCC::CondCodes getCondCode() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000490 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000491 return CC.Val;
492 }
493
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000494 unsigned getCoproc() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000495 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000496 return Cop.Val;
497 }
498
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000499 StringRef getToken() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000500 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000501 return StringRef(Tok.Data, Tok.Length);
502 }
503
504 unsigned getReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000505 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling7729e062010-11-09 22:44:22 +0000506 return Reg.RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000507 }
508
Bill Wendling5fa22a12010-11-09 23:28:44 +0000509 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000510 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
511 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling24d22d22010-11-18 21:50:54 +0000512 return Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000513 }
514
Kevin Enderbycfe07242009-10-13 22:19:02 +0000515 const MCExpr *getImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000516 assert(isImm() && "Invalid access!");
Kevin Enderbycfe07242009-10-13 22:19:02 +0000517 return Imm.Val;
518 }
519
Jim Grosbach460a9052011-10-07 23:56:00 +0000520 unsigned getVectorIndex() const {
521 assert(Kind == k_VectorIndex && "Invalid access!");
522 return VectorIndex.Val;
523 }
524
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000525 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000526 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000527 return MBOpt.Val;
528 }
529
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000530 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000531 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000532 return IFlags.Val;
533 }
534
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000535 unsigned getMSRMask() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000536 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000537 return MMask.Val;
538 }
539
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000540 bool isCoprocNum() const { return Kind == k_CoprocNum; }
541 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000542 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000543 bool isCondCode() const { return Kind == k_CondCode; }
544 bool isCCOut() const { return Kind == k_CCOut; }
545 bool isITMask() const { return Kind == k_ITCondMask; }
546 bool isITCondCode() const { return Kind == k_CondCode; }
547 bool isImm() const { return Kind == k_Immediate; }
Jim Grosbach51222d12012-01-20 18:09:51 +0000548 bool isFPImm() const {
549 if (!isImm()) return false;
550 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
551 if (!CE) return false;
552 int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
553 return Val != -1;
554 }
Jim Grosbach4050bc42011-12-22 22:19:05 +0000555 bool isFBits16() const {
556 if (!isImm()) return false;
557 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
558 if (!CE) return false;
559 int64_t Value = CE->getValue();
560 return Value >= 0 && Value <= 16;
561 }
562 bool isFBits32() const {
563 if (!isImm()) return false;
564 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
565 if (!CE) return false;
566 int64_t Value = CE->getValue();
567 return Value >= 1 && Value <= 32;
568 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000569 bool isImm8s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000570 if (!isImm()) return false;
Jim Grosbacha77295d2011-09-08 22:07:06 +0000571 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
572 if (!CE) return false;
573 int64_t Value = CE->getValue();
574 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
575 }
Jim Grosbach72f39f82011-08-24 21:22:15 +0000576 bool isImm0_1020s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000577 if (!isImm()) return false;
Jim Grosbach72f39f82011-08-24 21:22:15 +0000578 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
579 if (!CE) return false;
580 int64_t Value = CE->getValue();
581 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
582 }
583 bool isImm0_508s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000584 if (!isImm()) return false;
Jim Grosbach72f39f82011-08-24 21:22:15 +0000585 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
586 if (!CE) return false;
587 int64_t Value = CE->getValue();
588 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
589 }
Jim Grosbach4e53fe82012-04-05 20:57:13 +0000590 bool isImm0_508s4Neg() const {
591 if (!isImm()) return false;
592 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
593 if (!CE) return false;
594 int64_t Value = -CE->getValue();
595 // explicitly exclude zero. we want that to use the normal 0_508 version.
596 return ((Value & 3) == 0) && Value > 0 && Value <= 508;
597 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000598 bool isImm0_255() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000599 if (!isImm()) return false;
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000600 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
601 if (!CE) return false;
602 int64_t Value = CE->getValue();
603 return Value >= 0 && Value < 256;
604 }
Jim Grosbach4e53fe82012-04-05 20:57:13 +0000605 bool isImm0_4095() const {
606 if (!isImm()) return false;
607 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
608 if (!CE) return false;
609 int64_t Value = CE->getValue();
610 return Value >= 0 && Value < 4096;
611 }
612 bool isImm0_4095Neg() const {
613 if (!isImm()) return false;
614 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
615 if (!CE) return false;
616 int64_t Value = -CE->getValue();
617 return Value > 0 && Value < 4096;
618 }
Jim Grosbach587f5062011-12-02 23:34:39 +0000619 bool isImm0_1() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000620 if (!isImm()) return false;
Jim Grosbach587f5062011-12-02 23:34:39 +0000621 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
622 if (!CE) return false;
623 int64_t Value = CE->getValue();
624 return Value >= 0 && Value < 2;
625 }
626 bool isImm0_3() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000627 if (!isImm()) return false;
Jim Grosbach587f5062011-12-02 23:34:39 +0000628 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
629 if (!CE) return false;
630 int64_t Value = CE->getValue();
631 return Value >= 0 && Value < 4;
632 }
Jim Grosbach83ab0702011-07-13 22:01:08 +0000633 bool isImm0_7() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000634 if (!isImm()) return false;
Jim Grosbach83ab0702011-07-13 22:01:08 +0000635 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
636 if (!CE) return false;
637 int64_t Value = CE->getValue();
638 return Value >= 0 && Value < 8;
639 }
640 bool isImm0_15() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000641 if (!isImm()) return false;
Jim Grosbach83ab0702011-07-13 22:01:08 +0000642 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
643 if (!CE) return false;
644 int64_t Value = CE->getValue();
645 return Value >= 0 && Value < 16;
646 }
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000647 bool isImm0_31() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000648 if (!isImm()) return false;
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000649 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
650 if (!CE) return false;
651 int64_t Value = CE->getValue();
652 return Value >= 0 && Value < 32;
653 }
Jim Grosbach730fe6c2011-12-08 01:30:04 +0000654 bool isImm0_63() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000655 if (!isImm()) return false;
Jim Grosbach730fe6c2011-12-08 01:30:04 +0000656 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
657 if (!CE) return false;
658 int64_t Value = CE->getValue();
659 return Value >= 0 && Value < 64;
660 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000661 bool isImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000662 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000663 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
664 if (!CE) return false;
665 int64_t Value = CE->getValue();
666 return Value == 8;
667 }
668 bool isImm16() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000669 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000670 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
671 if (!CE) return false;
672 int64_t Value = CE->getValue();
673 return Value == 16;
674 }
675 bool isImm32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000676 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000677 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
678 if (!CE) return false;
679 int64_t Value = CE->getValue();
680 return Value == 32;
681 }
Jim Grosbach6b044c22011-12-08 22:06:06 +0000682 bool isShrImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000683 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000684 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
685 if (!CE) return false;
686 int64_t Value = CE->getValue();
687 return Value > 0 && Value <= 8;
688 }
689 bool isShrImm16() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000690 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000691 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
692 if (!CE) return false;
693 int64_t Value = CE->getValue();
694 return Value > 0 && Value <= 16;
695 }
696 bool isShrImm32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000697 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000698 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
699 if (!CE) return false;
700 int64_t Value = CE->getValue();
701 return Value > 0 && Value <= 32;
702 }
703 bool isShrImm64() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000704 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000705 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
706 if (!CE) return false;
707 int64_t Value = CE->getValue();
708 return Value > 0 && Value <= 64;
709 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000710 bool isImm1_7() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000711 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000712 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
713 if (!CE) return false;
714 int64_t Value = CE->getValue();
715 return Value > 0 && Value < 8;
716 }
717 bool isImm1_15() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000718 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000719 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
720 if (!CE) return false;
721 int64_t Value = CE->getValue();
722 return Value > 0 && Value < 16;
723 }
724 bool isImm1_31() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000725 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000726 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
727 if (!CE) return false;
728 int64_t Value = CE->getValue();
729 return Value > 0 && Value < 32;
730 }
Jim Grosbachf4943352011-07-25 23:09:14 +0000731 bool isImm1_16() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000732 if (!isImm()) return false;
Jim Grosbachf4943352011-07-25 23:09:14 +0000733 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
734 if (!CE) return false;
735 int64_t Value = CE->getValue();
736 return Value > 0 && Value < 17;
737 }
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000738 bool isImm1_32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000739 if (!isImm()) return false;
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000740 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
741 if (!CE) return false;
742 int64_t Value = CE->getValue();
743 return Value > 0 && Value < 33;
744 }
Jim Grosbachee10ff82011-11-10 19:18:01 +0000745 bool isImm0_32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000746 if (!isImm()) return false;
Jim Grosbachee10ff82011-11-10 19:18:01 +0000747 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
748 if (!CE) return false;
749 int64_t Value = CE->getValue();
750 return Value >= 0 && Value < 33;
751 }
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000752 bool isImm0_65535() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000753 if (!isImm()) return false;
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000754 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
755 if (!CE) return false;
756 int64_t Value = CE->getValue();
757 return Value >= 0 && Value < 65536;
758 }
Jim Grosbachffa32252011-07-19 19:13:28 +0000759 bool isImm0_65535Expr() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000760 if (!isImm()) return false;
Jim Grosbachffa32252011-07-19 19:13:28 +0000761 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
762 // If it's not a constant expression, it'll generate a fixup and be
763 // handled later.
764 if (!CE) return true;
765 int64_t Value = CE->getValue();
766 return Value >= 0 && Value < 65536;
767 }
Jim Grosbached838482011-07-26 16:24:27 +0000768 bool isImm24bit() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000769 if (!isImm()) return false;
Jim Grosbached838482011-07-26 16:24:27 +0000770 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
771 if (!CE) return false;
772 int64_t Value = CE->getValue();
773 return Value >= 0 && Value <= 0xffffff;
774 }
Jim Grosbach70939ee2011-08-17 21:51:27 +0000775 bool isImmThumbSR() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000776 if (!isImm()) return false;
Jim Grosbach70939ee2011-08-17 21:51:27 +0000777 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
778 if (!CE) return false;
779 int64_t Value = CE->getValue();
780 return Value > 0 && Value < 33;
781 }
Jim Grosbachf6c05252011-07-21 17:23:04 +0000782 bool isPKHLSLImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000783 if (!isImm()) return false;
Jim Grosbachf6c05252011-07-21 17:23:04 +0000784 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
785 if (!CE) return false;
786 int64_t Value = CE->getValue();
787 return Value >= 0 && Value < 32;
788 }
789 bool isPKHASRImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000790 if (!isImm()) return false;
Jim Grosbachf6c05252011-07-21 17:23:04 +0000791 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
792 if (!CE) return false;
793 int64_t Value = CE->getValue();
794 return Value > 0 && Value <= 32;
795 }
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000796 bool isARMSOImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000797 if (!isImm()) return false;
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000798 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
799 if (!CE) return false;
800 int64_t Value = CE->getValue();
801 return ARM_AM::getSOImmVal(Value) != -1;
802 }
Jim Grosbache70ec842011-10-28 22:50:54 +0000803 bool isARMSOImmNot() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000804 if (!isImm()) return false;
Jim Grosbache70ec842011-10-28 22:50:54 +0000805 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
806 if (!CE) return false;
807 int64_t Value = CE->getValue();
808 return ARM_AM::getSOImmVal(~Value) != -1;
809 }
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000810 bool isARMSOImmNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000811 if (!isImm()) return false;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000812 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
813 if (!CE) return false;
814 int64_t Value = CE->getValue();
Jim Grosbachad353c62012-03-30 19:59:02 +0000815 // Only use this when not representable as a plain so_imm.
816 return ARM_AM::getSOImmVal(Value) == -1 &&
817 ARM_AM::getSOImmVal(-Value) != -1;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000818 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000819 bool isT2SOImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000820 if (!isImm()) return false;
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000821 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
822 if (!CE) return false;
823 int64_t Value = CE->getValue();
824 return ARM_AM::getT2SOImmVal(Value) != -1;
825 }
Jim Grosbach89a63372011-10-28 22:36:30 +0000826 bool isT2SOImmNot() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000827 if (!isImm()) return false;
Jim Grosbach89a63372011-10-28 22:36:30 +0000828 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
829 if (!CE) return false;
830 int64_t Value = CE->getValue();
831 return ARM_AM::getT2SOImmVal(~Value) != -1;
832 }
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000833 bool isT2SOImmNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000834 if (!isImm()) return false;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000835 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
836 if (!CE) return false;
837 int64_t Value = CE->getValue();
Jim Grosbachad353c62012-03-30 19:59:02 +0000838 // Only use this when not representable as a plain so_imm.
839 return ARM_AM::getT2SOImmVal(Value) == -1 &&
840 ARM_AM::getT2SOImmVal(-Value) != -1;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000841 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000842 bool isSetEndImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000843 if (!isImm()) return false;
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000844 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
845 if (!CE) return false;
846 int64_t Value = CE->getValue();
847 return Value == 1 || Value == 0;
848 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000849 bool isReg() const { return Kind == k_Register; }
850 bool isRegList() const { return Kind == k_RegisterList; }
851 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
852 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
853 bool isToken() const { return Kind == k_Token; }
854 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
855 bool isMemory() const { return Kind == k_Memory; }
856 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
857 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
858 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
859 bool isRotImm() const { return Kind == k_RotateImmediate; }
860 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
861 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000862 bool isPostIdxReg() const {
Jim Grosbach430052b2011-11-14 17:52:47 +0000863 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000864 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000865 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000866 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000867 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000868 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000869 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
870 (alignOK || Memory.Alignment == 0);
871 }
Jim Grosbach0b4c6732012-01-18 22:46:46 +0000872 bool isMemPCRelImm12() const {
873 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
874 return false;
875 // Base register must be PC.
876 if (Memory.BaseRegNum != ARM::PC)
877 return false;
878 // Immediate offset in range [-4095, 4095].
879 if (!Memory.OffsetImm) return true;
880 int64_t Val = Memory.OffsetImm->getValue();
881 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
882 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000883 bool isAlignedMemory() const {
884 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000885 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000886 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000887 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000888 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000889 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000890 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000891 if (!Memory.OffsetImm) return true;
892 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000893 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000894 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000895 bool isAM2OffsetImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000896 if (!isImm()) return false;
Jim Grosbach039c2e12011-08-04 23:01:30 +0000897 // Immediate offset in range [-4095, 4095].
898 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
899 if (!CE) return false;
900 int64_t Val = CE->getValue();
901 return Val > -4096 && Val < 4096;
902 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000903 bool isAddrMode3() const {
Jim Grosbach2f196742011-12-19 23:06:24 +0000904 // If we have an immediate that's not a constant, treat it as a label
905 // reference needing a fixup. If it is a constant, it's something else
906 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000907 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach2f196742011-12-19 23:06:24 +0000908 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000909 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000910 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000911 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000912 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000913 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000914 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000915 if (!Memory.OffsetImm) return true;
916 int64_t Val = Memory.OffsetImm->getValue();
Silviu Barangaca3cd412012-05-11 09:10:54 +0000917 // The #-0 offset is encoded as INT32_MIN, and we have to check
918 // for this too.
919 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000920 }
921 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000922 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000923 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000924 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000925 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
926 // Immediate offset in range [-255, 255].
927 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
928 if (!CE) return false;
929 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000930 // Special case, #-0 is INT32_MIN.
931 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000932 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000933 bool isAddrMode5() const {
Jim Grosbach681460f2011-11-01 01:24:45 +0000934 // If we have an immediate that's not a constant, treat it as a label
935 // reference needing a fixup. If it is a constant, it's something else
936 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000937 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach681460f2011-11-01 01:24:45 +0000938 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000939 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000940 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000941 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000942 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000943 if (!Memory.OffsetImm) return true;
944 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000945 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbach681460f2011-11-01 01:24:45 +0000946 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000947 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000948 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000949 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000950 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000951 return false;
952 return true;
953 }
954 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000955 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000956 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
957 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000958 return false;
959 return true;
960 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000961 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000962 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000963 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000964 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000965 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000966 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000967 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
968 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000969 return false;
970 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000971 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000972 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000973 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000974 return false;
975 return true;
976 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000977 bool isMemThumbRR() const {
978 // Thumb reg+reg addressing is simple. Just two registers, a base and
979 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000980 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000981 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000982 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000983 return isARMLowRegister(Memory.BaseRegNum) &&
984 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000985 }
986 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000987 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000988 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000989 return false;
990 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000991 if (!Memory.OffsetImm) return true;
992 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000993 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
994 }
Jim Grosbach38466302011-08-19 18:55:51 +0000995 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000996 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000997 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000998 return false;
999 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001000 if (!Memory.OffsetImm) return true;
1001 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +00001002 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
1003 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001004 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +00001005 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +00001006 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001007 return false;
1008 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001009 if (!Memory.OffsetImm) return true;
1010 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001011 return Val >= 0 && Val <= 31;
1012 }
Jim Grosbachecd85892011-08-19 18:13:48 +00001013 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001014 if (!isMemory() || Memory.OffsetRegNum != 0 ||
1015 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +00001016 return false;
1017 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001018 if (!Memory.OffsetImm) return true;
1019 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +00001020 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001021 }
Jim Grosbacha77295d2011-09-08 22:07:06 +00001022 bool isMemImm8s4Offset() const {
Jim Grosbach2f196742011-12-19 23:06:24 +00001023 // If we have an immediate that's not a constant, treat it as a label
1024 // reference needing a fixup. If it is a constant, it's something else
1025 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001026 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach2f196742011-12-19 23:06:24 +00001027 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +00001028 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +00001029 return false;
1030 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001031 if (!Memory.OffsetImm) return true;
1032 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +00001033 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
1034 }
Jim Grosbachb6aed502011-09-09 18:37:27 +00001035 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001036 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +00001037 return false;
1038 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001039 if (!Memory.OffsetImm) return true;
1040 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +00001041 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
1042 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001043 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001044 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001045 return false;
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001046 // Base reg of PC isn't allowed for these encodings.
1047 if (Memory.BaseRegNum == ARM::PC) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001048 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001049 if (!Memory.OffsetImm) return true;
1050 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +00001051 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001052 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001053 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001054 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001055 return false;
1056 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001057 if (!Memory.OffsetImm) return true;
1058 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001059 return Val >= 0 && Val < 256;
1060 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001061 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001062 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001063 return false;
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001064 // Base reg of PC isn't allowed for these encodings.
1065 if (Memory.BaseRegNum == ARM::PC) return false;
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001066 // Immediate offset in range [-255, -1].
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001067 if (!Memory.OffsetImm) return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001068 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001069 return (Val == INT32_MIN) || (Val > -256 && Val < 0);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001070 }
1071 bool isMemUImm12Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001072 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001073 return false;
1074 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001075 if (!Memory.OffsetImm) return true;
1076 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001077 return (Val >= 0 && Val < 4096);
1078 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001079 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +00001080 // If we have an immediate that's not a constant, treat it as a label
1081 // reference needing a fixup. If it is a constant, it's something else
1082 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001083 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +00001084 return true;
1085
Jim Grosbach57dcb852011-10-11 17:29:55 +00001086 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001087 return false;
1088 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001089 if (!Memory.OffsetImm) return true;
1090 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +00001091 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001092 }
1093 bool isPostIdxImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001094 if (!isImm()) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001095 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1096 if (!CE) return false;
1097 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +00001098 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001099 }
Jim Grosbach2bd01182011-10-11 21:55:36 +00001100 bool isPostIdxImm8s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001101 if (!isImm()) return false;
Jim Grosbach2bd01182011-10-11 21:55:36 +00001102 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1103 if (!CE) return false;
1104 int64_t Val = CE->getValue();
1105 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1106 (Val == INT32_MIN);
1107 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001108
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001109 bool isMSRMask() const { return Kind == k_MSRMask; }
1110 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001111
Jim Grosbach0e387b22011-10-17 22:26:03 +00001112 // NEON operands.
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001113 bool isSingleSpacedVectorList() const {
1114 return Kind == k_VectorList && !VectorList.isDoubleSpaced;
1115 }
1116 bool isDoubleSpacedVectorList() const {
1117 return Kind == k_VectorList && VectorList.isDoubleSpaced;
1118 }
Jim Grosbach862019c2011-10-18 23:02:30 +00001119 bool isVecListOneD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001120 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach862019c2011-10-18 23:02:30 +00001121 return VectorList.Count == 1;
1122 }
1123
Jim Grosbach28f08c92012-03-05 19:33:30 +00001124 bool isVecListDPair() const {
1125 if (!isSingleSpacedVectorList()) return false;
1126 return (ARMMCRegisterClasses[ARM::DPairRegClassID]
1127 .contains(VectorList.RegNum));
1128 }
1129
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001130 bool isVecListThreeD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001131 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001132 return VectorList.Count == 3;
1133 }
1134
Jim Grosbachb6310312011-10-21 20:35:01 +00001135 bool isVecListFourD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001136 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachb6310312011-10-21 20:35:01 +00001137 return VectorList.Count == 4;
1138 }
1139
Jim Grosbachc3384c92012-03-05 21:43:40 +00001140 bool isVecListDPairSpaced() const {
Kevin Enderby9f2e1602012-03-20 17:41:51 +00001141 if (isSingleSpacedVectorList()) return false;
Jim Grosbachc3384c92012-03-05 21:43:40 +00001142 return (ARMMCRegisterClasses[ARM::DPairSpcRegClassID]
1143 .contains(VectorList.RegNum));
1144 }
1145
Jim Grosbachc387fc62012-01-23 23:20:46 +00001146 bool isVecListThreeQ() const {
1147 if (!isDoubleSpacedVectorList()) return false;
1148 return VectorList.Count == 3;
1149 }
1150
Jim Grosbach7945ead2012-01-24 00:43:12 +00001151 bool isVecListFourQ() const {
1152 if (!isDoubleSpacedVectorList()) return false;
1153 return VectorList.Count == 4;
1154 }
1155
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001156 bool isSingleSpacedVectorAllLanes() const {
1157 return Kind == k_VectorListAllLanes && !VectorList.isDoubleSpaced;
1158 }
1159 bool isDoubleSpacedVectorAllLanes() const {
1160 return Kind == k_VectorListAllLanes && VectorList.isDoubleSpaced;
1161 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00001162 bool isVecListOneDAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001163 if (!isSingleSpacedVectorAllLanes()) return false;
Jim Grosbach98b05a52011-11-30 01:09:44 +00001164 return VectorList.Count == 1;
1165 }
1166
Jim Grosbachc0fc4502012-03-06 22:01:44 +00001167 bool isVecListDPairAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001168 if (!isSingleSpacedVectorAllLanes()) return false;
Jim Grosbachc0fc4502012-03-06 22:01:44 +00001169 return (ARMMCRegisterClasses[ARM::DPairRegClassID]
1170 .contains(VectorList.RegNum));
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001171 }
1172
Jim Grosbach4d0983a2012-03-06 23:10:38 +00001173 bool isVecListDPairSpacedAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001174 if (!isDoubleSpacedVectorAllLanes()) return false;
Jim Grosbach13af2222011-11-30 18:21:25 +00001175 return VectorList.Count == 2;
1176 }
1177
Jim Grosbach5e59f7e2012-01-24 23:47:04 +00001178 bool isVecListThreeDAllLanes() const {
1179 if (!isSingleSpacedVectorAllLanes()) return false;
1180 return VectorList.Count == 3;
1181 }
1182
1183 bool isVecListThreeQAllLanes() const {
1184 if (!isDoubleSpacedVectorAllLanes()) return false;
1185 return VectorList.Count == 3;
1186 }
1187
Jim Grosbacha57a36a2012-01-25 00:01:08 +00001188 bool isVecListFourDAllLanes() const {
1189 if (!isSingleSpacedVectorAllLanes()) return false;
1190 return VectorList.Count == 4;
1191 }
1192
1193 bool isVecListFourQAllLanes() const {
1194 if (!isDoubleSpacedVectorAllLanes()) return false;
1195 return VectorList.Count == 4;
1196 }
1197
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001198 bool isSingleSpacedVectorIndexed() const {
1199 return Kind == k_VectorListIndexed && !VectorList.isDoubleSpaced;
1200 }
1201 bool isDoubleSpacedVectorIndexed() const {
1202 return Kind == k_VectorListIndexed && VectorList.isDoubleSpaced;
1203 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00001204 bool isVecListOneDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001205 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach7636bf62011-12-02 00:35:16 +00001206 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1207 }
1208
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001209 bool isVecListOneDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001210 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001211 return VectorList.Count == 1 && VectorList.LaneIndex <= 3;
1212 }
1213
1214 bool isVecListOneDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001215 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001216 return VectorList.Count == 1 && VectorList.LaneIndex <= 1;
1217 }
1218
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001219 bool isVecListTwoDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001220 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001221 return VectorList.Count == 2 && VectorList.LaneIndex <= 7;
1222 }
1223
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001224 bool isVecListTwoDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001225 if (!isSingleSpacedVectorIndexed()) return false;
1226 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1227 }
1228
1229 bool isVecListTwoQWordIndexed() const {
1230 if (!isDoubleSpacedVectorIndexed()) return false;
1231 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1232 }
1233
1234 bool isVecListTwoQHWordIndexed() const {
1235 if (!isDoubleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001236 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1237 }
1238
1239 bool isVecListTwoDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001240 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001241 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1242 }
1243
Jim Grosbach3a678af2012-01-23 21:53:26 +00001244 bool isVecListThreeDByteIndexed() const {
1245 if (!isSingleSpacedVectorIndexed()) return false;
1246 return VectorList.Count == 3 && VectorList.LaneIndex <= 7;
1247 }
1248
1249 bool isVecListThreeDHWordIndexed() const {
1250 if (!isSingleSpacedVectorIndexed()) return false;
1251 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1252 }
1253
1254 bool isVecListThreeQWordIndexed() const {
1255 if (!isDoubleSpacedVectorIndexed()) return false;
1256 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1257 }
1258
1259 bool isVecListThreeQHWordIndexed() const {
1260 if (!isDoubleSpacedVectorIndexed()) return false;
1261 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1262 }
1263
1264 bool isVecListThreeDWordIndexed() const {
1265 if (!isSingleSpacedVectorIndexed()) return false;
1266 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1267 }
1268
Jim Grosbache983a132012-01-24 18:37:25 +00001269 bool isVecListFourDByteIndexed() const {
1270 if (!isSingleSpacedVectorIndexed()) return false;
1271 return VectorList.Count == 4 && VectorList.LaneIndex <= 7;
1272 }
1273
1274 bool isVecListFourDHWordIndexed() const {
1275 if (!isSingleSpacedVectorIndexed()) return false;
1276 return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1277 }
1278
1279 bool isVecListFourQWordIndexed() const {
1280 if (!isDoubleSpacedVectorIndexed()) return false;
1281 return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1282 }
1283
1284 bool isVecListFourQHWordIndexed() const {
1285 if (!isDoubleSpacedVectorIndexed()) return false;
1286 return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1287 }
1288
1289 bool isVecListFourDWordIndexed() const {
1290 if (!isSingleSpacedVectorIndexed()) return false;
1291 return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1292 }
1293
Jim Grosbach460a9052011-10-07 23:56:00 +00001294 bool isVectorIndex8() const {
1295 if (Kind != k_VectorIndex) return false;
1296 return VectorIndex.Val < 8;
1297 }
1298 bool isVectorIndex16() const {
1299 if (Kind != k_VectorIndex) return false;
1300 return VectorIndex.Val < 4;
1301 }
1302 bool isVectorIndex32() const {
1303 if (Kind != k_VectorIndex) return false;
1304 return VectorIndex.Val < 2;
1305 }
1306
Jim Grosbach0e387b22011-10-17 22:26:03 +00001307 bool isNEONi8splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001308 if (!isImm()) return false;
Jim Grosbach0e387b22011-10-17 22:26:03 +00001309 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1310 // Must be a constant.
1311 if (!CE) return false;
1312 int64_t Value = CE->getValue();
1313 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1314 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +00001315 return Value >= 0 && Value < 256;
1316 }
Jim Grosbach460a9052011-10-07 23:56:00 +00001317
Jim Grosbachea461102011-10-17 23:09:09 +00001318 bool isNEONi16splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001319 if (!isImm()) return false;
Jim Grosbachea461102011-10-17 23:09:09 +00001320 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1321 // Must be a constant.
1322 if (!CE) return false;
1323 int64_t Value = CE->getValue();
1324 // i16 value in the range [0,255] or [0x0100, 0xff00]
1325 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1326 }
1327
Jim Grosbach6248a542011-10-18 00:22:00 +00001328 bool isNEONi32splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001329 if (!isImm()) return false;
Jim Grosbach6248a542011-10-18 00:22:00 +00001330 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1331 // Must be a constant.
1332 if (!CE) return false;
1333 int64_t Value = CE->getValue();
1334 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1335 return (Value >= 0 && Value < 256) ||
1336 (Value >= 0x0100 && Value <= 0xff00) ||
1337 (Value >= 0x010000 && Value <= 0xff0000) ||
1338 (Value >= 0x01000000 && Value <= 0xff000000);
1339 }
1340
1341 bool isNEONi32vmov() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001342 if (!isImm()) return false;
Jim Grosbach6248a542011-10-18 00:22:00 +00001343 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1344 // Must be a constant.
1345 if (!CE) return false;
1346 int64_t Value = CE->getValue();
1347 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1348 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1349 return (Value >= 0 && Value < 256) ||
1350 (Value >= 0x0100 && Value <= 0xff00) ||
1351 (Value >= 0x010000 && Value <= 0xff0000) ||
1352 (Value >= 0x01000000 && Value <= 0xff000000) ||
1353 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1354 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1355 }
Jim Grosbach9b087852011-12-19 23:51:07 +00001356 bool isNEONi32vmovNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001357 if (!isImm()) return false;
Jim Grosbach9b087852011-12-19 23:51:07 +00001358 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1359 // Must be a constant.
1360 if (!CE) return false;
1361 int64_t Value = ~CE->getValue();
1362 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1363 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1364 return (Value >= 0 && Value < 256) ||
1365 (Value >= 0x0100 && Value <= 0xff00) ||
1366 (Value >= 0x010000 && Value <= 0xff0000) ||
1367 (Value >= 0x01000000 && Value <= 0xff000000) ||
1368 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1369 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1370 }
Jim Grosbach6248a542011-10-18 00:22:00 +00001371
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001372 bool isNEONi64splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001373 if (!isImm()) return false;
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001374 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1375 // Must be a constant.
1376 if (!CE) return false;
1377 uint64_t Value = CE->getValue();
1378 // i64 value with each byte being either 0 or 0xff.
1379 for (unsigned i = 0; i < 8; ++i)
1380 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1381 return true;
1382 }
1383
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001384 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001385 // Add as immediates when possible. Null MCExpr = 0.
1386 if (Expr == 0)
1387 Inst.addOperand(MCOperand::CreateImm(0));
1388 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001389 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1390 else
1391 Inst.addOperand(MCOperand::CreateExpr(Expr));
1392 }
1393
Daniel Dunbar8462b302010-08-11 06:36:53 +00001394 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001395 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001396 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001397 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1398 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001399 }
1400
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001401 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1402 assert(N == 1 && "Invalid number of operands!");
1403 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1404 }
1405
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001406 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1407 assert(N == 1 && "Invalid number of operands!");
1408 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1409 }
1410
1411 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1412 assert(N == 1 && "Invalid number of operands!");
1413 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1414 }
1415
Jim Grosbach89df9962011-08-26 21:43:41 +00001416 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1417 assert(N == 1 && "Invalid number of operands!");
1418 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1419 }
1420
1421 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1422 assert(N == 1 && "Invalid number of operands!");
1423 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1424 }
1425
Jim Grosbachd67641b2010-12-06 18:21:12 +00001426 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1427 assert(N == 1 && "Invalid number of operands!");
1428 Inst.addOperand(MCOperand::CreateReg(getReg()));
1429 }
1430
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001431 void addRegOperands(MCInst &Inst, unsigned N) const {
1432 assert(N == 1 && "Invalid number of operands!");
1433 Inst.addOperand(MCOperand::CreateReg(getReg()));
1434 }
1435
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001436 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001437 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001438 assert(isRegShiftedReg() &&
1439 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001440 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1441 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001442 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001443 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001444 }
1445
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001446 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001447 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001448 assert(isRegShiftedImm() &&
1449 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001450 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Richard Bartonb56e4112012-04-25 18:00:18 +00001451 // Shift of #32 is encoded as 0 where permitted
1452 unsigned Imm = (RegShiftedImm.ShiftImm == 32 ? 0 : RegShiftedImm.ShiftImm);
Owen Anderson92a20222011-07-21 18:54:16 +00001453 Inst.addOperand(MCOperand::CreateImm(
Richard Bartonb56e4112012-04-25 18:00:18 +00001454 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, Imm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001455 }
1456
Jim Grosbach580f4a92011-07-25 22:20:28 +00001457 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001458 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001459 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1460 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001461 }
1462
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001463 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001464 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001465 const SmallVectorImpl<unsigned> &RegList = getRegList();
1466 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001467 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1468 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001469 }
1470
Bill Wendling0f630752010-11-17 04:32:08 +00001471 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1472 addRegListOperands(Inst, N);
1473 }
1474
1475 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1476 addRegListOperands(Inst, N);
1477 }
1478
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001479 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1480 assert(N == 1 && "Invalid number of operands!");
1481 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1482 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1483 }
1484
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001485 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1486 assert(N == 1 && "Invalid number of operands!");
1487 // Munge the lsb/width into a bitfield mask.
1488 unsigned lsb = Bitfield.LSB;
1489 unsigned width = Bitfield.Width;
1490 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1491 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1492 (32 - (lsb + width)));
1493 Inst.addOperand(MCOperand::CreateImm(Mask));
1494 }
1495
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001496 void addImmOperands(MCInst &Inst, unsigned N) const {
1497 assert(N == 1 && "Invalid number of operands!");
1498 addExpr(Inst, getImm());
1499 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001500
Jim Grosbach4050bc42011-12-22 22:19:05 +00001501 void addFBits16Operands(MCInst &Inst, unsigned N) const {
1502 assert(N == 1 && "Invalid number of operands!");
1503 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1504 Inst.addOperand(MCOperand::CreateImm(16 - CE->getValue()));
1505 }
1506
1507 void addFBits32Operands(MCInst &Inst, unsigned N) const {
1508 assert(N == 1 && "Invalid number of operands!");
1509 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1510 Inst.addOperand(MCOperand::CreateImm(32 - CE->getValue()));
1511 }
1512
Jim Grosbach9d390362011-10-03 23:38:36 +00001513 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1514 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach51222d12012-01-20 18:09:51 +00001515 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1516 int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
1517 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach9d390362011-10-03 23:38:36 +00001518 }
1519
Jim Grosbacha77295d2011-09-08 22:07:06 +00001520 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1521 assert(N == 1 && "Invalid number of operands!");
1522 // FIXME: We really want to scale the value here, but the LDRD/STRD
1523 // instruction don't encode operands that way yet.
1524 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1525 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1526 }
1527
Jim Grosbach72f39f82011-08-24 21:22:15 +00001528 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1529 assert(N == 1 && "Invalid number of operands!");
1530 // The immediate is scaled by four in the encoding and is stored
1531 // in the MCInst as such. Lop off the low two bits here.
1532 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1533 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1534 }
1535
Jim Grosbach4e53fe82012-04-05 20:57:13 +00001536 void addImm0_508s4NegOperands(MCInst &Inst, unsigned N) const {
1537 assert(N == 1 && "Invalid number of operands!");
1538 // The immediate is scaled by four in the encoding and is stored
1539 // in the MCInst as such. Lop off the low two bits here.
1540 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1541 Inst.addOperand(MCOperand::CreateImm(-(CE->getValue() / 4)));
1542 }
1543
Jim Grosbach72f39f82011-08-24 21:22:15 +00001544 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1545 assert(N == 1 && "Invalid number of operands!");
1546 // The immediate is scaled by four in the encoding and is stored
1547 // in the MCInst as such. Lop off the low two bits here.
1548 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1549 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1550 }
1551
Jim Grosbachf4943352011-07-25 23:09:14 +00001552 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1553 assert(N == 1 && "Invalid number of operands!");
1554 // The constant encodes as the immediate-1, and we store in the instruction
1555 // the bits as encoded, so subtract off one here.
1556 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1557 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1558 }
1559
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001560 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1561 assert(N == 1 && "Invalid number of operands!");
1562 // The constant encodes as the immediate-1, and we store in the instruction
1563 // the bits as encoded, so subtract off one here.
1564 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1565 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1566 }
1567
Jim Grosbach70939ee2011-08-17 21:51:27 +00001568 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1569 assert(N == 1 && "Invalid number of operands!");
1570 // The constant encodes as the immediate, except for 32, which encodes as
1571 // zero.
1572 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1573 unsigned Imm = CE->getValue();
1574 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1575 }
1576
Jim Grosbachf6c05252011-07-21 17:23:04 +00001577 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1578 assert(N == 1 && "Invalid number of operands!");
1579 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1580 // the instruction as well.
1581 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1582 int Val = CE->getValue();
1583 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1584 }
1585
Jim Grosbach89a63372011-10-28 22:36:30 +00001586 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1587 assert(N == 1 && "Invalid number of operands!");
1588 // The operand is actually a t2_so_imm, but we have its bitwise
1589 // negation in the assembly source, so twiddle it here.
1590 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1591 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1592 }
1593
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001594 void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1595 assert(N == 1 && "Invalid number of operands!");
1596 // The operand is actually a t2_so_imm, but we have its
1597 // negation in the assembly source, so twiddle it here.
1598 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1599 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1600 }
1601
Jim Grosbach4e53fe82012-04-05 20:57:13 +00001602 void addImm0_4095NegOperands(MCInst &Inst, unsigned N) const {
1603 assert(N == 1 && "Invalid number of operands!");
1604 // The operand is actually an imm0_4095, but we have its
1605 // negation in the assembly source, so twiddle it here.
1606 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1607 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1608 }
1609
Jim Grosbache70ec842011-10-28 22:50:54 +00001610 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1611 assert(N == 1 && "Invalid number of operands!");
1612 // The operand is actually a so_imm, but we have its bitwise
1613 // negation in the assembly source, so twiddle it here.
1614 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1615 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1616 }
1617
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001618 void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
1619 assert(N == 1 && "Invalid number of operands!");
1620 // The operand is actually a so_imm, but we have its
1621 // negation in the assembly source, so twiddle it here.
1622 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1623 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1624 }
1625
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001626 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1627 assert(N == 1 && "Invalid number of operands!");
1628 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1629 }
1630
Jim Grosbach7ce05792011-08-03 23:50:40 +00001631 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1632 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001633 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001634 }
1635
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001636 void addMemPCRelImm12Operands(MCInst &Inst, unsigned N) const {
1637 assert(N == 1 && "Invalid number of operands!");
1638 int32_t Imm = Memory.OffsetImm->getValue();
1639 // FIXME: Handle #-0
1640 if (Imm == INT32_MIN) Imm = 0;
1641 Inst.addOperand(MCOperand::CreateImm(Imm));
1642 }
1643
Jim Grosbach57dcb852011-10-11 17:29:55 +00001644 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1645 assert(N == 2 && "Invalid number of operands!");
1646 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1647 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1648 }
1649
Jim Grosbach7ce05792011-08-03 23:50:40 +00001650 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1651 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001652 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1653 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001654 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1655 // Special case for #-0
1656 if (Val == INT32_MIN) Val = 0;
1657 if (Val < 0) Val = -Val;
1658 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1659 } else {
1660 // For register offset, we encode the shift type and negation flag
1661 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001662 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1663 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001664 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001665 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1666 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001667 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001668 }
1669
Jim Grosbach039c2e12011-08-04 23:01:30 +00001670 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1671 assert(N == 2 && "Invalid number of operands!");
1672 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1673 assert(CE && "non-constant AM2OffsetImm operand!");
1674 int32_t Val = CE->getValue();
1675 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1676 // Special case for #-0
1677 if (Val == INT32_MIN) Val = 0;
1678 if (Val < 0) Val = -Val;
1679 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1680 Inst.addOperand(MCOperand::CreateReg(0));
1681 Inst.addOperand(MCOperand::CreateImm(Val));
1682 }
1683
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001684 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1685 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001686 // If we have an immediate that's not a constant, treat it as a label
1687 // reference needing a fixup. If it is a constant, it's something else
1688 // and we reject it.
1689 if (isImm()) {
1690 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1691 Inst.addOperand(MCOperand::CreateReg(0));
1692 Inst.addOperand(MCOperand::CreateImm(0));
1693 return;
1694 }
1695
Jim Grosbache53c87b2011-10-11 15:59:20 +00001696 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1697 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001698 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1699 // Special case for #-0
1700 if (Val == INT32_MIN) Val = 0;
1701 if (Val < 0) Val = -Val;
1702 Val = ARM_AM::getAM3Opc(AddSub, Val);
1703 } else {
1704 // For register offset, we encode the shift type and negation flag
1705 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001706 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001707 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001708 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1709 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001710 Inst.addOperand(MCOperand::CreateImm(Val));
1711 }
1712
1713 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1714 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001715 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001716 int32_t Val =
1717 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1718 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1719 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001720 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001721 }
1722
1723 // Constant offset.
1724 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1725 int32_t Val = CE->getValue();
1726 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1727 // Special case for #-0
1728 if (Val == INT32_MIN) Val = 0;
1729 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001730 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001731 Inst.addOperand(MCOperand::CreateReg(0));
1732 Inst.addOperand(MCOperand::CreateImm(Val));
1733 }
1734
Jim Grosbach7ce05792011-08-03 23:50:40 +00001735 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1736 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach681460f2011-11-01 01:24:45 +00001737 // If we have an immediate that's not a constant, treat it as a label
1738 // reference needing a fixup. If it is a constant, it's something else
1739 // and we reject it.
1740 if (isImm()) {
1741 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1742 Inst.addOperand(MCOperand::CreateImm(0));
1743 return;
1744 }
1745
Jim Grosbach7ce05792011-08-03 23:50:40 +00001746 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001747 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001748 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1749 // Special case for #-0
1750 if (Val == INT32_MIN) Val = 0;
1751 if (Val < 0) Val = -Val;
1752 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001753 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001754 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001755 }
1756
Jim Grosbacha77295d2011-09-08 22:07:06 +00001757 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1758 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001759 // If we have an immediate that's not a constant, treat it as a label
1760 // reference needing a fixup. If it is a constant, it's something else
1761 // and we reject it.
1762 if (isImm()) {
1763 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1764 Inst.addOperand(MCOperand::CreateImm(0));
1765 return;
1766 }
1767
Jim Grosbache53c87b2011-10-11 15:59:20 +00001768 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1769 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001770 Inst.addOperand(MCOperand::CreateImm(Val));
1771 }
1772
Jim Grosbachb6aed502011-09-09 18:37:27 +00001773 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1774 assert(N == 2 && "Invalid number of operands!");
1775 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001776 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1777 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001778 Inst.addOperand(MCOperand::CreateImm(Val));
1779 }
1780
Jim Grosbach7ce05792011-08-03 23:50:40 +00001781 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1782 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001783 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1784 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001785 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001786 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001787
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001788 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1789 addMemImm8OffsetOperands(Inst, N);
1790 }
1791
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001792 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001793 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001794 }
1795
1796 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1797 assert(N == 2 && "Invalid number of operands!");
1798 // If this is an immediate, it's a label reference.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001799 if (isImm()) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001800 addExpr(Inst, getImm());
1801 Inst.addOperand(MCOperand::CreateImm(0));
1802 return;
1803 }
1804
1805 // Otherwise, it's a normal memory reg+offset.
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 Grosbacha8307dd2011-09-07 20:58:57 +00001808 Inst.addOperand(MCOperand::CreateImm(Val));
1809 }
1810
Jim Grosbach7ce05792011-08-03 23:50:40 +00001811 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1812 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001813 // If this is an immediate, it's a label reference.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001814 if (isImm()) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001815 addExpr(Inst, getImm());
1816 Inst.addOperand(MCOperand::CreateImm(0));
1817 return;
1818 }
1819
1820 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001821 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1822 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001823 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001824 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001825
Jim Grosbach7f739be2011-09-19 22:21:13 +00001826 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1827 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001828 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1829 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001830 }
1831
1832 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1833 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001834 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1835 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001836 }
1837
Jim Grosbach7ce05792011-08-03 23:50:40 +00001838 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1839 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001840 unsigned Val =
1841 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1842 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001843 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1844 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001845 Inst.addOperand(MCOperand::CreateImm(Val));
1846 }
1847
Jim Grosbachab899c12011-09-07 23:10:15 +00001848 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1849 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001850 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1851 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1852 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001853 }
1854
Jim Grosbach7ce05792011-08-03 23:50:40 +00001855 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1856 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001857 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1858 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001859 }
1860
Jim Grosbach60f91a32011-08-19 17:55:24 +00001861 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1862 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001863 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1864 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001865 Inst.addOperand(MCOperand::CreateImm(Val));
1866 }
1867
Jim Grosbach38466302011-08-19 18:55:51 +00001868 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1869 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001870 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1871 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001872 Inst.addOperand(MCOperand::CreateImm(Val));
1873 }
1874
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001875 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1876 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001877 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1878 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001879 Inst.addOperand(MCOperand::CreateImm(Val));
1880 }
1881
Jim Grosbachecd85892011-08-19 18:13:48 +00001882 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1883 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001884 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1885 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001886 Inst.addOperand(MCOperand::CreateImm(Val));
1887 }
1888
Jim Grosbach7ce05792011-08-03 23:50:40 +00001889 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1890 assert(N == 1 && "Invalid number of operands!");
1891 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1892 assert(CE && "non-constant post-idx-imm8 operand!");
1893 int Imm = CE->getValue();
1894 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001895 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001896 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1897 Inst.addOperand(MCOperand::CreateImm(Imm));
1898 }
1899
Jim Grosbach2bd01182011-10-11 21:55:36 +00001900 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1901 assert(N == 1 && "Invalid number of operands!");
1902 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1903 assert(CE && "non-constant post-idx-imm8s4 operand!");
1904 int Imm = CE->getValue();
1905 bool isAdd = Imm >= 0;
1906 if (Imm == INT32_MIN) Imm = 0;
1907 // Immediate is scaled by 4.
1908 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1909 Inst.addOperand(MCOperand::CreateImm(Imm));
1910 }
1911
Jim Grosbach7ce05792011-08-03 23:50:40 +00001912 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1913 assert(N == 2 && "Invalid number of operands!");
1914 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001915 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1916 }
1917
1918 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1919 assert(N == 2 && "Invalid number of operands!");
1920 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1921 // The sign, shift type, and shift amount are encoded in a single operand
1922 // using the AM2 encoding helpers.
1923 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1924 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1925 PostIdxReg.ShiftTy);
1926 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001927 }
1928
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001929 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1930 assert(N == 1 && "Invalid number of operands!");
1931 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1932 }
1933
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001934 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1935 assert(N == 1 && "Invalid number of operands!");
1936 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1937 }
1938
Jim Grosbach6029b6d2011-11-29 23:51:09 +00001939 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach862019c2011-10-18 23:02:30 +00001940 assert(N == 1 && "Invalid number of operands!");
1941 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1942 }
1943
Jim Grosbach7636bf62011-12-02 00:35:16 +00001944 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1945 assert(N == 2 && "Invalid number of operands!");
1946 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1947 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1948 }
1949
Jim Grosbach460a9052011-10-07 23:56:00 +00001950 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1951 assert(N == 1 && "Invalid number of operands!");
1952 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1953 }
1954
1955 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1956 assert(N == 1 && "Invalid number of operands!");
1957 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1958 }
1959
1960 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1961 assert(N == 1 && "Invalid number of operands!");
1962 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1963 }
1964
Jim Grosbach0e387b22011-10-17 22:26:03 +00001965 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1966 assert(N == 1 && "Invalid number of operands!");
1967 // The immediate encodes the type of constant as well as the value.
1968 // Mask in that this is an i8 splat.
1969 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1970 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1971 }
1972
Jim Grosbachea461102011-10-17 23:09:09 +00001973 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1974 assert(N == 1 && "Invalid number of operands!");
1975 // The immediate encodes the type of constant as well as the value.
1976 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1977 unsigned Value = CE->getValue();
1978 if (Value >= 256)
1979 Value = (Value >> 8) | 0xa00;
1980 else
1981 Value |= 0x800;
1982 Inst.addOperand(MCOperand::CreateImm(Value));
1983 }
1984
Jim Grosbach6248a542011-10-18 00:22:00 +00001985 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1986 assert(N == 1 && "Invalid number of operands!");
1987 // The immediate encodes the type of constant as well as the value.
1988 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1989 unsigned Value = CE->getValue();
1990 if (Value >= 256 && Value <= 0xff00)
1991 Value = (Value >> 8) | 0x200;
1992 else if (Value > 0xffff && Value <= 0xff0000)
1993 Value = (Value >> 16) | 0x400;
1994 else if (Value > 0xffffff)
1995 Value = (Value >> 24) | 0x600;
1996 Inst.addOperand(MCOperand::CreateImm(Value));
1997 }
1998
1999 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
2000 assert(N == 1 && "Invalid number of operands!");
2001 // The immediate encodes the type of constant as well as the value.
2002 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2003 unsigned Value = CE->getValue();
2004 if (Value >= 256 && Value <= 0xffff)
2005 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
2006 else if (Value > 0xffff && Value <= 0xffffff)
2007 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
2008 else if (Value > 0xffffff)
2009 Value = (Value >> 24) | 0x600;
2010 Inst.addOperand(MCOperand::CreateImm(Value));
2011 }
2012
Jim Grosbach9b087852011-12-19 23:51:07 +00002013 void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const {
2014 assert(N == 1 && "Invalid number of operands!");
2015 // The immediate encodes the type of constant as well as the value.
2016 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2017 unsigned Value = ~CE->getValue();
2018 if (Value >= 256 && Value <= 0xffff)
2019 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
2020 else if (Value > 0xffff && Value <= 0xffffff)
2021 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
2022 else if (Value > 0xffffff)
2023 Value = (Value >> 24) | 0x600;
2024 Inst.addOperand(MCOperand::CreateImm(Value));
2025 }
2026
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00002027 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
2028 assert(N == 1 && "Invalid number of operands!");
2029 // The immediate encodes the type of constant as well as the value.
2030 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2031 uint64_t Value = CE->getValue();
2032 unsigned Imm = 0;
2033 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
2034 Imm |= (Value & 1) << i;
2035 }
2036 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
2037 }
2038
Jim Grosbachb7f689b2011-07-13 15:34:57 +00002039 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00002040
Jim Grosbach89df9962011-08-26 21:43:41 +00002041 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002042 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00002043 Op->ITMask.Mask = Mask;
2044 Op->StartLoc = S;
2045 Op->EndLoc = S;
2046 return Op;
2047 }
2048
Chris Lattner3a697562010-10-28 17:20:03 +00002049 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002050 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00002051 Op->CC.Val = CC;
2052 Op->StartLoc = S;
2053 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00002054 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00002055 }
2056
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002057 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002058 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002059 Op->Cop.Val = CopVal;
2060 Op->StartLoc = S;
2061 Op->EndLoc = S;
2062 return Op;
2063 }
2064
2065 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002066 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002067 Op->Cop.Val = CopVal;
2068 Op->StartLoc = S;
2069 Op->EndLoc = S;
2070 return Op;
2071 }
2072
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002073 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
2074 ARMOperand *Op = new ARMOperand(k_CoprocOption);
2075 Op->Cop.Val = Val;
2076 Op->StartLoc = S;
2077 Op->EndLoc = E;
2078 return Op;
2079 }
2080
Jim Grosbachd67641b2010-12-06 18:21:12 +00002081 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002082 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00002083 Op->Reg.RegNum = RegNum;
2084 Op->StartLoc = S;
2085 Op->EndLoc = S;
2086 return Op;
2087 }
2088
Chris Lattner3a697562010-10-28 17:20:03 +00002089 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002090 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00002091 Op->Tok.Data = Str.data();
2092 Op->Tok.Length = Str.size();
2093 Op->StartLoc = S;
2094 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00002095 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002096 }
2097
Bill Wendling50d0f582010-11-18 23:43:05 +00002098 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002099 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00002100 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00002101 Op->StartLoc = S;
2102 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002103 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002104 }
2105
Jim Grosbache8606dc2011-07-13 17:50:29 +00002106 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
2107 unsigned SrcReg,
2108 unsigned ShiftReg,
2109 unsigned ShiftImm,
2110 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002111 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002112 Op->RegShiftedReg.ShiftTy = ShTy;
2113 Op->RegShiftedReg.SrcReg = SrcReg;
2114 Op->RegShiftedReg.ShiftReg = ShiftReg;
2115 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002116 Op->StartLoc = S;
2117 Op->EndLoc = E;
2118 return Op;
2119 }
2120
Owen Anderson92a20222011-07-21 18:54:16 +00002121 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
2122 unsigned SrcReg,
2123 unsigned ShiftImm,
2124 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002125 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002126 Op->RegShiftedImm.ShiftTy = ShTy;
2127 Op->RegShiftedImm.SrcReg = SrcReg;
2128 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00002129 Op->StartLoc = S;
2130 Op->EndLoc = E;
2131 return Op;
2132 }
2133
Jim Grosbach580f4a92011-07-25 22:20:28 +00002134 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002135 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002136 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00002137 Op->ShifterImm.isASR = isASR;
2138 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00002139 Op->StartLoc = S;
2140 Op->EndLoc = E;
2141 return Op;
2142 }
2143
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002144 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002145 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002146 Op->RotImm.Imm = Imm;
2147 Op->StartLoc = S;
2148 Op->EndLoc = E;
2149 return Op;
2150 }
2151
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002152 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
2153 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002154 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002155 Op->Bitfield.LSB = LSB;
2156 Op->Bitfield.Width = Width;
2157 Op->StartLoc = S;
2158 Op->EndLoc = E;
2159 return Op;
2160 }
2161
Bill Wendling7729e062010-11-09 22:44:22 +00002162 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00002163 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002164 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002165 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002166
Jim Grosbachd300b942011-09-13 22:56:44 +00002167 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002168 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00002169 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00002170 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002171 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002172
2173 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00002174 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002175 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00002176 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00002177 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002178 Op->StartLoc = StartLoc;
2179 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00002180 return Op;
2181 }
2182
Jim Grosbach862019c2011-10-18 23:02:30 +00002183 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002184 bool isDoubleSpaced, SMLoc S, SMLoc E) {
Jim Grosbach862019c2011-10-18 23:02:30 +00002185 ARMOperand *Op = new ARMOperand(k_VectorList);
2186 Op->VectorList.RegNum = RegNum;
2187 Op->VectorList.Count = Count;
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002188 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach862019c2011-10-18 23:02:30 +00002189 Op->StartLoc = S;
2190 Op->EndLoc = E;
2191 return Op;
2192 }
2193
Jim Grosbach98b05a52011-11-30 01:09:44 +00002194 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002195 bool isDoubleSpaced,
Jim Grosbach98b05a52011-11-30 01:09:44 +00002196 SMLoc S, SMLoc E) {
2197 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
2198 Op->VectorList.RegNum = RegNum;
2199 Op->VectorList.Count = Count;
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002200 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002201 Op->StartLoc = S;
2202 Op->EndLoc = E;
2203 return Op;
2204 }
2205
Jim Grosbach7636bf62011-12-02 00:35:16 +00002206 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002207 unsigned Index,
2208 bool isDoubleSpaced,
2209 SMLoc S, SMLoc E) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002210 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
2211 Op->VectorList.RegNum = RegNum;
2212 Op->VectorList.Count = Count;
2213 Op->VectorList.LaneIndex = Index;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002214 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002215 Op->StartLoc = S;
2216 Op->EndLoc = E;
2217 return Op;
2218 }
2219
Jim Grosbach460a9052011-10-07 23:56:00 +00002220 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
2221 MCContext &Ctx) {
2222 ARMOperand *Op = new ARMOperand(k_VectorIndex);
2223 Op->VectorIndex.Val = Idx;
2224 Op->StartLoc = S;
2225 Op->EndLoc = E;
2226 return Op;
2227 }
2228
Chris Lattner3a697562010-10-28 17:20:03 +00002229 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002230 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00002231 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00002232 Op->StartLoc = S;
2233 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002234 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00002235 }
2236
Jim Grosbach7ce05792011-08-03 23:50:40 +00002237 static ARMOperand *CreateMem(unsigned BaseRegNum,
2238 const MCConstantExpr *OffsetImm,
2239 unsigned OffsetRegNum,
2240 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002241 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00002242 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002243 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00002244 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002245 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00002246 Op->Memory.BaseRegNum = BaseRegNum;
2247 Op->Memory.OffsetImm = OffsetImm;
2248 Op->Memory.OffsetRegNum = OffsetRegNum;
2249 Op->Memory.ShiftType = ShiftType;
2250 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00002251 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00002252 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002253 Op->StartLoc = S;
2254 Op->EndLoc = E;
2255 return Op;
2256 }
Jim Grosbach16c74252010-10-29 14:46:02 +00002257
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002258 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
2259 ARM_AM::ShiftOpc ShiftTy,
2260 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002261 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002262 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002263 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002264 Op->PostIdxReg.isAdd = isAdd;
2265 Op->PostIdxReg.ShiftTy = ShiftTy;
2266 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00002267 Op->StartLoc = S;
2268 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002269 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002270 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002271
2272 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002273 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002274 Op->MBOpt.Val = Opt;
2275 Op->StartLoc = S;
2276 Op->EndLoc = S;
2277 return Op;
2278 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002279
2280 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002281 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002282 Op->IFlags.Val = IFlags;
2283 Op->StartLoc = S;
2284 Op->EndLoc = S;
2285 return Op;
2286 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002287
2288 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002289 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002290 Op->MMask.Val = MMask;
2291 Op->StartLoc = S;
2292 Op->EndLoc = S;
2293 return Op;
2294 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002295};
2296
2297} // end anonymous namespace.
2298
Jim Grosbachb7f689b2011-07-13 15:34:57 +00002299void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002300 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002301 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00002302 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002303 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002304 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00002305 OS << "<ccout " << getReg() << ">";
2306 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002307 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002308 static const char *MaskStr[] = {
2309 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2310 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2311 };
Jim Grosbach89df9962011-08-26 21:43:41 +00002312 assert((ITMask.Mask & 0xf) == ITMask.Mask);
2313 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2314 break;
2315 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002316 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002317 OS << "<coprocessor number: " << getCoproc() << ">";
2318 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002319 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002320 OS << "<coprocessor register: " << getCoproc() << ">";
2321 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002322 case k_CoprocOption:
2323 OS << "<coprocessor option: " << CoprocOption.Val << ">";
2324 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002325 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002326 OS << "<mask: " << getMSRMask() << ">";
2327 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002328 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002329 getImm()->print(OS);
2330 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002331 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002332 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2333 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002334 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002335 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00002336 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002337 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002338 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002339 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002340 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2341 << PostIdxReg.RegNum;
2342 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2343 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2344 << PostIdxReg.ShiftImm;
2345 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00002346 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002347 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002348 OS << "<ARM_PROC::";
2349 unsigned IFlags = getProcIFlags();
2350 for (int i=2; i >= 0; --i)
2351 if (IFlags & (1 << i))
2352 OS << ARM_PROC::IFlagsToString(1 << i);
2353 OS << ">";
2354 break;
2355 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002356 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00002357 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002358 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002359 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00002360 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2361 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00002362 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002363 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00002364 OS << "<so_reg_reg "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002365 << RegShiftedReg.SrcReg << " "
2366 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2367 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson00828302011-03-18 22:50:18 +00002368 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002369 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00002370 OS << "<so_reg_imm "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002371 << RegShiftedImm.SrcReg << " "
2372 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2373 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Anderson92a20222011-07-21 18:54:16 +00002374 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002375 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002376 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2377 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002378 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002379 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2380 << ", width: " << Bitfield.Width << ">";
2381 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002382 case k_RegisterList:
2383 case k_DPRRegisterList:
2384 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00002385 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002386
Bill Wendling5fa22a12010-11-09 23:28:44 +00002387 const SmallVectorImpl<unsigned> &RegList = getRegList();
2388 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002389 I = RegList.begin(), E = RegList.end(); I != E; ) {
2390 OS << *I;
2391 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002392 }
2393
2394 OS << ">";
2395 break;
2396 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002397 case k_VectorList:
2398 OS << "<vector_list " << VectorList.Count << " * "
2399 << VectorList.RegNum << ">";
2400 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002401 case k_VectorListAllLanes:
2402 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2403 << VectorList.RegNum << ">";
2404 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002405 case k_VectorListIndexed:
2406 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2407 << VectorList.Count << " * " << VectorList.RegNum << ">";
2408 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002409 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002410 OS << "'" << getToken() << "'";
2411 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00002412 case k_VectorIndex:
2413 OS << "<vectorindex " << getVectorIndex() << ">";
2414 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002415 }
2416}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00002417
2418/// @name Auto-generated Match Functions
2419/// {
2420
2421static unsigned MatchRegisterName(StringRef Name);
2422
2423/// }
2424
Bob Wilson69df7232011-02-03 21:46:10 +00002425bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2426 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbacha39cda72011-12-14 02:16:11 +00002427 StartLoc = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002428 RegNo = tryParseRegister();
Jim Grosbacha39cda72011-12-14 02:16:11 +00002429 EndLoc = Parser.getTok().getLoc();
Roman Divackybf755322011-01-27 17:14:22 +00002430
2431 return (RegNo == (unsigned)-1);
2432}
2433
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002434/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002435/// and if it is a register name the token is eaten and the register number is
2436/// returned. Otherwise return -1.
2437///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002438int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002439 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002440 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002441
Benjamin Kramer59085362011-11-06 20:37:06 +00002442 std::string lowerCase = Tok.getString().lower();
Owen Anderson0c9f2502011-01-13 22:50:36 +00002443 unsigned RegNum = MatchRegisterName(lowerCase);
2444 if (!RegNum) {
2445 RegNum = StringSwitch<unsigned>(lowerCase)
2446 .Case("r13", ARM::SP)
2447 .Case("r14", ARM::LR)
2448 .Case("r15", ARM::PC)
2449 .Case("ip", ARM::R12)
Jim Grosbach40e28552011-12-08 19:27:38 +00002450 // Additional register name aliases for 'gas' compatibility.
2451 .Case("a1", ARM::R0)
2452 .Case("a2", ARM::R1)
2453 .Case("a3", ARM::R2)
2454 .Case("a4", ARM::R3)
2455 .Case("v1", ARM::R4)
2456 .Case("v2", ARM::R5)
2457 .Case("v3", ARM::R6)
2458 .Case("v4", ARM::R7)
2459 .Case("v5", ARM::R8)
2460 .Case("v6", ARM::R9)
2461 .Case("v7", ARM::R10)
2462 .Case("v8", ARM::R11)
2463 .Case("sb", ARM::R9)
2464 .Case("sl", ARM::R10)
2465 .Case("fp", ARM::R11)
Owen Anderson0c9f2502011-01-13 22:50:36 +00002466 .Default(0);
2467 }
Jim Grosbacha39cda72011-12-14 02:16:11 +00002468 if (!RegNum) {
Jim Grosbachaee718b2011-12-20 23:11:00 +00002469 // Check for aliases registered via .req. Canonicalize to lower case.
2470 // That's more consistent since register names are case insensitive, and
2471 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2472 StringMap<unsigned>::const_iterator Entry = RegisterReqs.find(lowerCase);
Jim Grosbacha39cda72011-12-14 02:16:11 +00002473 // If no match, return failure.
2474 if (Entry == RegisterReqs.end())
2475 return -1;
2476 Parser.Lex(); // Eat identifier token.
2477 return Entry->getValue();
2478 }
Bob Wilson69df7232011-02-03 21:46:10 +00002479
Chris Lattnere5658fa2010-10-30 04:09:10 +00002480 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002481
Chris Lattnere5658fa2010-10-30 04:09:10 +00002482 return RegNum;
2483}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002484
Jim Grosbach19906722011-07-13 18:49:30 +00002485// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2486// If a recoverable error occurs, return 1. If an irrecoverable error
2487// occurs, return -1. An irrecoverable error is one where tokens have been
2488// consumed in the process of trying to parse the shifter (i.e., when it is
2489// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002490int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002491 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2492 SMLoc S = Parser.getTok().getLoc();
2493 const AsmToken &Tok = Parser.getTok();
2494 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2495
Benjamin Kramer59085362011-11-06 20:37:06 +00002496 std::string lowerCase = Tok.getString().lower();
Owen Anderson00828302011-03-18 22:50:18 +00002497 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbachaf4edea2011-12-07 23:40:58 +00002498 .Case("asl", ARM_AM::lsl)
Owen Anderson00828302011-03-18 22:50:18 +00002499 .Case("lsl", ARM_AM::lsl)
2500 .Case("lsr", ARM_AM::lsr)
2501 .Case("asr", ARM_AM::asr)
2502 .Case("ror", ARM_AM::ror)
2503 .Case("rrx", ARM_AM::rrx)
2504 .Default(ARM_AM::no_shift);
2505
2506 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002507 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002508
Jim Grosbache8606dc2011-07-13 17:50:29 +00002509 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002510
Jim Grosbache8606dc2011-07-13 17:50:29 +00002511 // The source register for the shift has already been added to the
2512 // operand list, so we need to pop it off and combine it into the shifted
2513 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002514 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002515 if (!PrevOp->isReg())
2516 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2517 int SrcReg = PrevOp->getReg();
2518 int64_t Imm = 0;
2519 int ShiftReg = 0;
2520 if (ShiftTy == ARM_AM::rrx) {
2521 // RRX Doesn't have an explicit shift amount. The encoder expects
2522 // the shift register to be the same as the source register. Seems odd,
2523 // but OK.
2524 ShiftReg = SrcReg;
2525 } else {
2526 // Figure out if this is shifted by a constant or a register (for non-RRX).
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00002527 if (Parser.getTok().is(AsmToken::Hash) ||
2528 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbache8606dc2011-07-13 17:50:29 +00002529 Parser.Lex(); // Eat hash.
2530 SMLoc ImmLoc = Parser.getTok().getLoc();
2531 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002532 if (getParser().ParseExpression(ShiftExpr)) {
2533 Error(ImmLoc, "invalid immediate shift value");
2534 return -1;
2535 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002536 // The expression must be evaluatable as an immediate.
2537 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002538 if (!CE) {
2539 Error(ImmLoc, "invalid immediate shift value");
2540 return -1;
2541 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002542 // Range check the immediate.
2543 // lsl, ror: 0 <= imm <= 31
2544 // lsr, asr: 0 <= imm <= 32
2545 Imm = CE->getValue();
2546 if (Imm < 0 ||
2547 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2548 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002549 Error(ImmLoc, "immediate shift value out of range");
2550 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002551 }
Jim Grosbachde626ad2011-12-22 17:37:00 +00002552 // shift by zero is a nop. Always send it through as lsl.
2553 // ('as' compatibility)
2554 if (Imm == 0)
2555 ShiftTy = ARM_AM::lsl;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002556 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002557 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002558 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002559 if (ShiftReg == -1) {
2560 Error (L, "expected immediate or register in shift operand");
2561 return -1;
2562 }
2563 } else {
2564 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002565 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002566 return -1;
2567 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002568 }
2569
Owen Anderson92a20222011-07-21 18:54:16 +00002570 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2571 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002572 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002573 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002574 else
2575 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2576 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002577
Jim Grosbach19906722011-07-13 18:49:30 +00002578 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002579}
2580
2581
Bill Wendling50d0f582010-11-18 23:43:05 +00002582/// Try to parse a register name. The token must be an Identifier when called.
2583/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2584/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002585///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002586/// TODO this is likely to change to allow different register types and or to
2587/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002588bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002589tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002590 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002591 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002592 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002593 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002594
Bill Wendling50d0f582010-11-18 23:43:05 +00002595 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002596
Chris Lattnere5658fa2010-10-30 04:09:10 +00002597 const AsmToken &ExclaimTok = Parser.getTok();
2598 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002599 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2600 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002601 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002602 return false;
2603 }
2604
2605 // Also check for an index operand. This is only legal for vector registers,
2606 // but that'll get caught OK in operand matching, so we don't need to
2607 // explicitly filter everything else out here.
2608 if (Parser.getTok().is(AsmToken::LBrac)) {
2609 SMLoc SIdx = Parser.getTok().getLoc();
2610 Parser.Lex(); // Eat left bracket token.
2611
2612 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002613 if (getParser().ParseExpression(ImmVal))
Jim Grosbach24dda212012-01-31 23:51:09 +00002614 return true;
Jim Grosbach460a9052011-10-07 23:56:00 +00002615 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbachef4d3eb2012-01-26 15:56:45 +00002616 if (!MCE)
2617 return TokError("immediate value expected for vector index");
Jim Grosbach460a9052011-10-07 23:56:00 +00002618
2619 SMLoc E = Parser.getTok().getLoc();
Jim Grosbachef4d3eb2012-01-26 15:56:45 +00002620 if (Parser.getTok().isNot(AsmToken::RBrac))
2621 return Error(E, "']' expected");
Jim Grosbach460a9052011-10-07 23:56:00 +00002622
2623 Parser.Lex(); // Eat right bracket token.
2624
2625 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2626 SIdx, E,
2627 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002628 }
2629
Bill Wendling50d0f582010-11-18 23:43:05 +00002630 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002631}
2632
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002633/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2634/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2635/// "c5", ...
2636static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002637 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2638 // but efficient.
2639 switch (Name.size()) {
David Blaikie4d6ccb52012-01-20 21:51:11 +00002640 default: return -1;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002641 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002642 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002643 return -1;
2644 switch (Name[1]) {
2645 default: return -1;
2646 case '0': return 0;
2647 case '1': return 1;
2648 case '2': return 2;
2649 case '3': return 3;
2650 case '4': return 4;
2651 case '5': return 5;
2652 case '6': return 6;
2653 case '7': return 7;
2654 case '8': return 8;
2655 case '9': return 9;
2656 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002657 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002658 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002659 return -1;
2660 switch (Name[2]) {
2661 default: return -1;
2662 case '0': return 10;
2663 case '1': return 11;
2664 case '2': return 12;
2665 case '3': return 13;
2666 case '4': return 14;
2667 case '5': return 15;
2668 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002669 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002670}
2671
Jim Grosbach89df9962011-08-26 21:43:41 +00002672/// parseITCondCode - Try to parse a condition code for an IT instruction.
2673ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2674parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2675 SMLoc S = Parser.getTok().getLoc();
2676 const AsmToken &Tok = Parser.getTok();
2677 if (!Tok.is(AsmToken::Identifier))
2678 return MatchOperand_NoMatch;
Richard Barton04a09a42012-04-27 17:34:01 +00002679 unsigned CC = StringSwitch<unsigned>(Tok.getString().lower())
Jim Grosbach89df9962011-08-26 21:43:41 +00002680 .Case("eq", ARMCC::EQ)
2681 .Case("ne", ARMCC::NE)
2682 .Case("hs", ARMCC::HS)
2683 .Case("cs", ARMCC::HS)
2684 .Case("lo", ARMCC::LO)
2685 .Case("cc", ARMCC::LO)
2686 .Case("mi", ARMCC::MI)
2687 .Case("pl", ARMCC::PL)
2688 .Case("vs", ARMCC::VS)
2689 .Case("vc", ARMCC::VC)
2690 .Case("hi", ARMCC::HI)
2691 .Case("ls", ARMCC::LS)
2692 .Case("ge", ARMCC::GE)
2693 .Case("lt", ARMCC::LT)
2694 .Case("gt", ARMCC::GT)
2695 .Case("le", ARMCC::LE)
2696 .Case("al", ARMCC::AL)
2697 .Default(~0U);
2698 if (CC == ~0U)
2699 return MatchOperand_NoMatch;
2700 Parser.Lex(); // Eat the token.
2701
2702 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2703
2704 return MatchOperand_Success;
2705}
2706
Jim Grosbach43904292011-07-25 20:14:50 +00002707/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002708/// token must be an Identifier when called, and if it is a coprocessor
2709/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002710ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002711parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002712 SMLoc S = Parser.getTok().getLoc();
2713 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002714 if (Tok.isNot(AsmToken::Identifier))
2715 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002716
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002717 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002718 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002719 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002720
2721 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002722 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002723 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002724}
2725
Jim Grosbach43904292011-07-25 20:14:50 +00002726/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002727/// token must be an Identifier when called, and if it is a coprocessor
2728/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002729ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002730parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002731 SMLoc S = Parser.getTok().getLoc();
2732 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002733 if (Tok.isNot(AsmToken::Identifier))
2734 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002735
2736 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2737 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002738 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002739
2740 Parser.Lex(); // Eat identifier token.
2741 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002742 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002743}
2744
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002745/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2746/// coproc_option : '{' imm0_255 '}'
2747ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2748parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2749 SMLoc S = Parser.getTok().getLoc();
2750
2751 // If this isn't a '{', this isn't a coprocessor immediate operand.
2752 if (Parser.getTok().isNot(AsmToken::LCurly))
2753 return MatchOperand_NoMatch;
2754 Parser.Lex(); // Eat the '{'
2755
2756 const MCExpr *Expr;
2757 SMLoc Loc = Parser.getTok().getLoc();
2758 if (getParser().ParseExpression(Expr)) {
2759 Error(Loc, "illegal expression");
2760 return MatchOperand_ParseFail;
2761 }
2762 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2763 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2764 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2765 return MatchOperand_ParseFail;
2766 }
2767 int Val = CE->getValue();
2768
2769 // Check for and consume the closing '}'
2770 if (Parser.getTok().isNot(AsmToken::RCurly))
2771 return MatchOperand_ParseFail;
2772 SMLoc E = Parser.getTok().getLoc();
2773 Parser.Lex(); // Eat the '}'
2774
2775 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2776 return MatchOperand_Success;
2777}
2778
Jim Grosbachd0588e22011-09-14 18:08:35 +00002779// For register list parsing, we need to map from raw GPR register numbering
2780// to the enumeration values. The enumeration values aren't sorted by
2781// register number due to our using "sp", "lr" and "pc" as canonical names.
2782static unsigned getNextRegister(unsigned Reg) {
2783 // If this is a GPR, we need to do it manually, otherwise we can rely
2784 // on the sort ordering of the enumeration since the other reg-classes
2785 // are sane.
2786 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2787 return Reg + 1;
2788 switch(Reg) {
Craig Topperbc219812012-02-07 02:50:20 +00002789 default: llvm_unreachable("Invalid GPR number!");
Jim Grosbachd0588e22011-09-14 18:08:35 +00002790 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2791 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2792 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2793 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2794 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2795 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2796 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2797 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2798 }
2799}
2800
Jim Grosbachce485e72011-11-11 21:27:40 +00002801// Return the low-subreg of a given Q register.
2802static unsigned getDRegFromQReg(unsigned QReg) {
2803 switch (QReg) {
2804 default: llvm_unreachable("expected a Q register!");
2805 case ARM::Q0: return ARM::D0;
2806 case ARM::Q1: return ARM::D2;
2807 case ARM::Q2: return ARM::D4;
2808 case ARM::Q3: return ARM::D6;
2809 case ARM::Q4: return ARM::D8;
2810 case ARM::Q5: return ARM::D10;
2811 case ARM::Q6: return ARM::D12;
2812 case ARM::Q7: return ARM::D14;
2813 case ARM::Q8: return ARM::D16;
Jim Grosbach25e0a872011-11-15 21:01:30 +00002814 case ARM::Q9: return ARM::D18;
Jim Grosbachce485e72011-11-11 21:27:40 +00002815 case ARM::Q10: return ARM::D20;
2816 case ARM::Q11: return ARM::D22;
2817 case ARM::Q12: return ARM::D24;
2818 case ARM::Q13: return ARM::D26;
2819 case ARM::Q14: return ARM::D28;
2820 case ARM::Q15: return ARM::D30;
2821 }
2822}
2823
Jim Grosbachd0588e22011-09-14 18:08:35 +00002824/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002825bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002826parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002827 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002828 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002829 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002830 Parser.Lex(); // Eat '{' token.
2831 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002832
Jim Grosbachd0588e22011-09-14 18:08:35 +00002833 // Check the first register in the list to see what register class
2834 // this is a list of.
2835 int Reg = tryParseRegister();
2836 if (Reg == -1)
2837 return Error(RegLoc, "register expected");
2838
Jim Grosbachce485e72011-11-11 21:27:40 +00002839 // The reglist instructions have at most 16 registers, so reserve
2840 // space for that many.
2841 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2842
2843 // Allow Q regs and just interpret them as the two D sub-registers.
2844 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2845 Reg = getDRegFromQReg(Reg);
2846 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2847 ++Reg;
2848 }
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002849 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002850 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2851 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2852 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2853 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2854 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2855 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2856 else
2857 return Error(RegLoc, "invalid register in register list");
2858
Jim Grosbachce485e72011-11-11 21:27:40 +00002859 // Store the register.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002860 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002861
Jim Grosbachd0588e22011-09-14 18:08:35 +00002862 // This starts immediately after the first register token in the list,
2863 // so we can see either a comma or a minus (range separator) as a legal
2864 // next token.
2865 while (Parser.getTok().is(AsmToken::Comma) ||
2866 Parser.getTok().is(AsmToken::Minus)) {
2867 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache43862b2011-11-15 23:19:15 +00002868 Parser.Lex(); // Eat the minus.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002869 SMLoc EndLoc = Parser.getTok().getLoc();
2870 int EndReg = tryParseRegister();
2871 if (EndReg == -1)
2872 return Error(EndLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002873 // Allow Q regs and just interpret them as the two D sub-registers.
2874 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2875 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002876 // If the register is the same as the start reg, there's nothing
2877 // more to do.
2878 if (Reg == EndReg)
2879 continue;
2880 // The register must be in the same register class as the first.
2881 if (!RC->contains(EndReg))
2882 return Error(EndLoc, "invalid register in register list");
2883 // Ranges must go from low to high.
2884 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2885 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002886
Jim Grosbachd0588e22011-09-14 18:08:35 +00002887 // Add all the registers in the range to the register list.
2888 while (Reg != EndReg) {
2889 Reg = getNextRegister(Reg);
2890 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2891 }
2892 continue;
2893 }
2894 Parser.Lex(); // Eat the comma.
2895 RegLoc = Parser.getTok().getLoc();
2896 int OldReg = Reg;
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002897 const AsmToken RegTok = Parser.getTok();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002898 Reg = tryParseRegister();
2899 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002900 return Error(RegLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002901 // Allow Q regs and just interpret them as the two D sub-registers.
2902 bool isQReg = false;
2903 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2904 Reg = getDRegFromQReg(Reg);
2905 isQReg = true;
2906 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002907 // The register must be in the same register class as the first.
2908 if (!RC->contains(Reg))
2909 return Error(RegLoc, "invalid register in register list");
2910 // List must be monotonically increasing.
Jim Grosbachbe7cf2b2012-03-16 20:48:38 +00002911 if (getARMRegisterNumbering(Reg) < getARMRegisterNumbering(OldReg)) {
2912 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2913 Warning(RegLoc, "register list not in ascending order");
2914 else
2915 return Error(RegLoc, "register list not in ascending order");
2916 }
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002917 if (getARMRegisterNumbering(Reg) == getARMRegisterNumbering(OldReg)) {
2918 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
2919 ") in register list");
2920 continue;
2921 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002922 // VFP register lists must also be contiguous.
2923 // It's OK to use the enumeration values directly here rather, as the
2924 // VFP register classes have the enum sorted properly.
2925 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2926 Reg != OldReg + 1)
2927 return Error(RegLoc, "non-contiguous register range");
2928 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbachce485e72011-11-11 21:27:40 +00002929 if (isQReg)
2930 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002931 }
2932
Jim Grosbachd0588e22011-09-14 18:08:35 +00002933 SMLoc E = Parser.getTok().getLoc();
2934 if (Parser.getTok().isNot(AsmToken::RCurly))
2935 return Error(E, "'}' expected");
2936 Parser.Lex(); // Eat '}' token.
2937
Jim Grosbach27debd62011-12-13 21:48:29 +00002938 // Push the register list operand.
Bill Wendling50d0f582010-11-18 23:43:05 +00002939 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
Jim Grosbach27debd62011-12-13 21:48:29 +00002940
2941 // The ARM system instruction variants for LDM/STM have a '^' token here.
2942 if (Parser.getTok().is(AsmToken::Caret)) {
2943 Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
2944 Parser.Lex(); // Eat '^' token.
2945 }
2946
Bill Wendling50d0f582010-11-18 23:43:05 +00002947 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002948}
2949
Jim Grosbach98b05a52011-11-30 01:09:44 +00002950// Helper function to parse the lane index for vector lists.
2951ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach7636bf62011-12-02 00:35:16 +00002952parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2953 Index = 0; // Always return a defined index value.
Jim Grosbach98b05a52011-11-30 01:09:44 +00002954 if (Parser.getTok().is(AsmToken::LBrac)) {
2955 Parser.Lex(); // Eat the '['.
2956 if (Parser.getTok().is(AsmToken::RBrac)) {
2957 // "Dn[]" is the 'all lanes' syntax.
2958 LaneKind = AllLanes;
2959 Parser.Lex(); // Eat the ']'.
2960 return MatchOperand_Success;
2961 }
Jim Grosbachceee9842012-03-19 20:39:53 +00002962
2963 // There's an optional '#' token here. Normally there wouldn't be, but
2964 // inline assemble puts one in, and it's friendly to accept that.
2965 if (Parser.getTok().is(AsmToken::Hash))
2966 Parser.Lex(); // Eat the '#'
2967
Jim Grosbachc9313252011-12-21 01:19:23 +00002968 const MCExpr *LaneIndex;
2969 SMLoc Loc = Parser.getTok().getLoc();
2970 if (getParser().ParseExpression(LaneIndex)) {
2971 Error(Loc, "illegal expression");
2972 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002973 }
Jim Grosbachc9313252011-12-21 01:19:23 +00002974 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LaneIndex);
2975 if (!CE) {
2976 Error(Loc, "lane index must be empty or an integer");
2977 return MatchOperand_ParseFail;
2978 }
2979 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2980 Error(Parser.getTok().getLoc(), "']' expected");
2981 return MatchOperand_ParseFail;
2982 }
2983 Parser.Lex(); // Eat the ']'.
2984 int64_t Val = CE->getValue();
2985
2986 // FIXME: Make this range check context sensitive for .8, .16, .32.
2987 if (Val < 0 || Val > 7) {
2988 Error(Parser.getTok().getLoc(), "lane index out of range");
2989 return MatchOperand_ParseFail;
2990 }
2991 Index = Val;
2992 LaneKind = IndexedLane;
2993 return MatchOperand_Success;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002994 }
2995 LaneKind = NoLanes;
2996 return MatchOperand_Success;
2997}
2998
Jim Grosbach862019c2011-10-18 23:02:30 +00002999// parse a vector register list
3000ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3001parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003002 VectorLaneTy LaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003003 unsigned LaneIndex;
Jim Grosbach5c984e42011-11-15 21:45:55 +00003004 SMLoc S = Parser.getTok().getLoc();
3005 // As an extension (to match gas), support a plain D register or Q register
3006 // (without encosing curly braces) as a single or double entry list,
3007 // respectively.
3008 if (Parser.getTok().is(AsmToken::Identifier)) {
3009 int Reg = tryParseRegister();
3010 if (Reg == -1)
3011 return MatchOperand_NoMatch;
3012 SMLoc E = Parser.getTok().getLoc();
3013 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00003014 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00003015 if (Res != MatchOperand_Success)
3016 return Res;
3017 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003018 case NoLanes:
3019 E = Parser.getTok().getLoc();
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003020 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003021 break;
3022 case AllLanes:
3023 E = Parser.getTok().getLoc();
Jim Grosbach3471d4f2011-12-21 00:38:54 +00003024 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false,
3025 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003026 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003027 case IndexedLane:
3028 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00003029 LaneIndex,
3030 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00003031 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003032 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00003033 return MatchOperand_Success;
3034 }
3035 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
3036 Reg = getDRegFromQReg(Reg);
Jim Grosbach7636bf62011-12-02 00:35:16 +00003037 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00003038 if (Res != MatchOperand_Success)
3039 return Res;
3040 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003041 case NoLanes:
3042 E = Parser.getTok().getLoc();
Jim Grosbach28f08c92012-03-05 19:33:30 +00003043 Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0,
Jim Grosbachc0fc4502012-03-06 22:01:44 +00003044 &ARMMCRegisterClasses[ARM::DPairRegClassID]);
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003045 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003046 break;
3047 case AllLanes:
3048 E = Parser.getTok().getLoc();
Jim Grosbachc0fc4502012-03-06 22:01:44 +00003049 Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0,
3050 &ARMMCRegisterClasses[ARM::DPairRegClassID]);
Jim Grosbach3471d4f2011-12-21 00:38:54 +00003051 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, false,
3052 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003053 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003054 case IndexedLane:
3055 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00003056 LaneIndex,
3057 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00003058 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003059 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00003060 return MatchOperand_Success;
3061 }
3062 Error(S, "vector register expected");
3063 return MatchOperand_ParseFail;
3064 }
3065
3066 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbach862019c2011-10-18 23:02:30 +00003067 return MatchOperand_NoMatch;
3068
Jim Grosbach862019c2011-10-18 23:02:30 +00003069 Parser.Lex(); // Eat '{' token.
3070 SMLoc RegLoc = Parser.getTok().getLoc();
3071
3072 int Reg = tryParseRegister();
3073 if (Reg == -1) {
3074 Error(RegLoc, "register expected");
3075 return MatchOperand_ParseFail;
3076 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003077 unsigned Count = 1;
Jim Grosbach276ed032011-12-15 21:54:55 +00003078 int Spacing = 0;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003079 unsigned FirstReg = Reg;
3080 // The list is of D registers, but we also allow Q regs and just interpret
3081 // them as the two D sub-registers.
3082 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
3083 FirstReg = Reg = getDRegFromQReg(Reg);
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003084 Spacing = 1; // double-spacing requires explicit D registers, otherwise
3085 // it's ambiguous with four-register single spaced.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003086 ++Reg;
3087 ++Count;
3088 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00003089 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003090 return MatchOperand_ParseFail;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003091
Jim Grosbache43862b2011-11-15 23:19:15 +00003092 while (Parser.getTok().is(AsmToken::Comma) ||
3093 Parser.getTok().is(AsmToken::Minus)) {
3094 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003095 if (!Spacing)
3096 Spacing = 1; // Register range implies a single spaced list.
3097 else if (Spacing == 2) {
3098 Error(Parser.getTok().getLoc(),
3099 "sequential registers in double spaced list");
3100 return MatchOperand_ParseFail;
3101 }
Jim Grosbache43862b2011-11-15 23:19:15 +00003102 Parser.Lex(); // Eat the minus.
3103 SMLoc EndLoc = Parser.getTok().getLoc();
3104 int EndReg = tryParseRegister();
3105 if (EndReg == -1) {
3106 Error(EndLoc, "register expected");
3107 return MatchOperand_ParseFail;
3108 }
3109 // Allow Q regs and just interpret them as the two D sub-registers.
3110 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
3111 EndReg = getDRegFromQReg(EndReg) + 1;
3112 // If the register is the same as the start reg, there's nothing
3113 // more to do.
3114 if (Reg == EndReg)
3115 continue;
3116 // The register must be in the same register class as the first.
3117 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
3118 Error(EndLoc, "invalid register in register list");
3119 return MatchOperand_ParseFail;
3120 }
3121 // Ranges must go from low to high.
3122 if (Reg > EndReg) {
3123 Error(EndLoc, "bad range in register list");
3124 return MatchOperand_ParseFail;
3125 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00003126 // Parse the lane specifier if present.
3127 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003128 unsigned NextLaneIndex;
3129 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003130 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003131 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003132 Error(EndLoc, "mismatched lane index in register list");
3133 return MatchOperand_ParseFail;
3134 }
3135 EndLoc = Parser.getTok().getLoc();
Jim Grosbache43862b2011-11-15 23:19:15 +00003136
3137 // Add all the registers in the range to the register list.
3138 Count += EndReg - Reg;
3139 Reg = EndReg;
3140 continue;
3141 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003142 Parser.Lex(); // Eat the comma.
3143 RegLoc = Parser.getTok().getLoc();
3144 int OldReg = Reg;
3145 Reg = tryParseRegister();
3146 if (Reg == -1) {
3147 Error(RegLoc, "register expected");
3148 return MatchOperand_ParseFail;
3149 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003150 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00003151 // It's OK to use the enumeration values directly here rather, as the
3152 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003153 //
3154 // The list is of D registers, but we also allow Q regs and just interpret
3155 // them as the two D sub-registers.
3156 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003157 if (!Spacing)
3158 Spacing = 1; // Register range implies a single spaced list.
3159 else if (Spacing == 2) {
3160 Error(RegLoc,
3161 "invalid register in double-spaced list (must be 'D' register')");
3162 return MatchOperand_ParseFail;
3163 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003164 Reg = getDRegFromQReg(Reg);
3165 if (Reg != OldReg + 1) {
3166 Error(RegLoc, "non-contiguous register range");
3167 return MatchOperand_ParseFail;
3168 }
3169 ++Reg;
3170 Count += 2;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003171 // Parse the lane specifier if present.
3172 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003173 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003174 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003175 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003176 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003177 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003178 Error(EndLoc, "mismatched lane index in register list");
3179 return MatchOperand_ParseFail;
3180 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003181 continue;
3182 }
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003183 // Normal D register.
3184 // Figure out the register spacing (single or double) of the list if
3185 // we don't know it already.
3186 if (!Spacing)
3187 Spacing = 1 + (Reg == OldReg + 2);
3188
3189 // Just check that it's contiguous and keep going.
3190 if (Reg != OldReg + Spacing) {
Jim Grosbach862019c2011-10-18 23:02:30 +00003191 Error(RegLoc, "non-contiguous register range");
3192 return MatchOperand_ParseFail;
3193 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003194 ++Count;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003195 // Parse the lane specifier if present.
3196 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003197 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003198 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003199 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003200 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003201 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003202 Error(EndLoc, "mismatched lane index in register list");
3203 return MatchOperand_ParseFail;
3204 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003205 }
3206
3207 SMLoc E = Parser.getTok().getLoc();
3208 if (Parser.getTok().isNot(AsmToken::RCurly)) {
3209 Error(E, "'}' expected");
3210 return MatchOperand_ParseFail;
3211 }
3212 Parser.Lex(); // Eat '}' token.
3213
Jim Grosbach98b05a52011-11-30 01:09:44 +00003214 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003215 case NoLanes:
Jim Grosbachc0fc4502012-03-06 22:01:44 +00003216 // Two-register operands have been converted to the
Jim Grosbachc3384c92012-03-05 21:43:40 +00003217 // composite register classes.
3218 if (Count == 2) {
3219 const MCRegisterClass *RC = (Spacing == 1) ?
3220 &ARMMCRegisterClasses[ARM::DPairRegClassID] :
3221 &ARMMCRegisterClasses[ARM::DPairSpcRegClassID];
3222 FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC);
3223 }
Jim Grosbach28f08c92012-03-05 19:33:30 +00003224
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003225 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count,
3226 (Spacing == 2), S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003227 break;
3228 case AllLanes:
Jim Grosbachc0fc4502012-03-06 22:01:44 +00003229 // Two-register operands have been converted to the
3230 // composite register classes.
Jim Grosbach4d0983a2012-03-06 23:10:38 +00003231 if (Count == 2) {
3232 const MCRegisterClass *RC = (Spacing == 1) ?
3233 &ARMMCRegisterClasses[ARM::DPairRegClassID] :
3234 &ARMMCRegisterClasses[ARM::DPairSpcRegClassID];
Jim Grosbachc0fc4502012-03-06 22:01:44 +00003235 FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC);
3236 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00003237 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00003238 (Spacing == 2),
Jim Grosbach98b05a52011-11-30 01:09:44 +00003239 S, E));
3240 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003241 case IndexedLane:
3242 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00003243 LaneIndex,
3244 (Spacing == 2),
3245 S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00003246 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003247 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003248 return MatchOperand_Success;
3249}
3250
Jim Grosbach43904292011-07-25 20:14:50 +00003251/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00003252ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003253parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003254 SMLoc S = Parser.getTok().getLoc();
3255 const AsmToken &Tok = Parser.getTok();
3256 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3257 StringRef OptStr = Tok.getString();
3258
3259 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
3260 .Case("sy", ARM_MB::SY)
3261 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003262 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003263 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003264 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003265 .Case("ishst", ARM_MB::ISHST)
3266 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003267 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003268 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003269 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003270 .Case("osh", ARM_MB::OSH)
3271 .Case("oshst", ARM_MB::OSHST)
3272 .Default(~0U);
3273
3274 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00003275 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003276
3277 Parser.Lex(); // Eat identifier token.
3278 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00003279 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003280}
3281
Jim Grosbach43904292011-07-25 20:14:50 +00003282/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003283ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003284parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003285 SMLoc S = Parser.getTok().getLoc();
3286 const AsmToken &Tok = Parser.getTok();
3287 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3288 StringRef IFlagsStr = Tok.getString();
3289
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003290 // An iflags string of "none" is interpreted to mean that none of the AIF
3291 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003292 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003293 if (IFlagsStr != "none") {
3294 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
3295 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
3296 .Case("a", ARM_PROC::A)
3297 .Case("i", ARM_PROC::I)
3298 .Case("f", ARM_PROC::F)
3299 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003300
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003301 // If some specific iflag is already set, it means that some letter is
3302 // present more than once, this is not acceptable.
3303 if (Flag == ~0U || (IFlags & Flag))
3304 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003305
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003306 IFlags |= Flag;
3307 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003308 }
3309
3310 Parser.Lex(); // Eat identifier token.
3311 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
3312 return MatchOperand_Success;
3313}
3314
Jim Grosbach43904292011-07-25 20:14:50 +00003315/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003316ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003317parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003318 SMLoc S = Parser.getTok().getLoc();
3319 const AsmToken &Tok = Parser.getTok();
3320 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3321 StringRef Mask = Tok.getString();
3322
James Molloyacad68d2011-09-28 14:21:38 +00003323 if (isMClass()) {
3324 // See ARMv6-M 10.1.1
Jim Grosbachb84ad4a2012-03-15 21:34:14 +00003325 std::string Name = Mask.lower();
3326 unsigned FlagsVal = StringSwitch<unsigned>(Name)
James Molloyacad68d2011-09-28 14:21:38 +00003327 .Case("apsr", 0)
3328 .Case("iapsr", 1)
3329 .Case("eapsr", 2)
3330 .Case("xpsr", 3)
3331 .Case("ipsr", 5)
3332 .Case("epsr", 6)
3333 .Case("iepsr", 7)
3334 .Case("msp", 8)
3335 .Case("psp", 9)
3336 .Case("primask", 16)
3337 .Case("basepri", 17)
3338 .Case("basepri_max", 18)
3339 .Case("faultmask", 19)
3340 .Case("control", 20)
3341 .Default(~0U);
Jim Grosbach18c8d122011-12-22 17:17:10 +00003342
James Molloyacad68d2011-09-28 14:21:38 +00003343 if (FlagsVal == ~0U)
3344 return MatchOperand_NoMatch;
3345
3346 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
3347 // basepri, basepri_max and faultmask only valid for V7m.
3348 return MatchOperand_NoMatch;
Jim Grosbach18c8d122011-12-22 17:17:10 +00003349
James Molloyacad68d2011-09-28 14:21:38 +00003350 Parser.Lex(); // Eat identifier token.
3351 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3352 return MatchOperand_Success;
3353 }
3354
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003355 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
3356 size_t Start = 0, Next = Mask.find('_');
3357 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00003358 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003359 if (Next != StringRef::npos)
3360 Flags = Mask.slice(Next+1, Mask.size());
3361
3362 // FlagsVal contains the complete mask:
3363 // 3-0: Mask
3364 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3365 unsigned FlagsVal = 0;
3366
3367 if (SpecReg == "apsr") {
3368 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00003369 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003370 .Case("g", 0x4) // same as CPSR_s
3371 .Case("nzcvqg", 0xc) // same as CPSR_fs
3372 .Default(~0U);
3373
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003374 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003375 if (!Flags.empty())
3376 return MatchOperand_NoMatch;
3377 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00003378 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003379 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003380 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Jim Grosbachb657a902012-04-05 03:17:53 +00003381 // cpsr_all is an alias for cpsr_fc, as is plain cpsr.
3382 if (Flags == "all" || Flags == "")
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00003383 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003384 for (int i = 0, e = Flags.size(); i != e; ++i) {
3385 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
3386 .Case("c", 1)
3387 .Case("x", 2)
3388 .Case("s", 4)
3389 .Case("f", 8)
3390 .Default(~0U);
3391
3392 // If some specific flag is already set, it means that some letter is
3393 // present more than once, this is not acceptable.
3394 if (FlagsVal == ~0U || (FlagsVal & Flag))
3395 return MatchOperand_NoMatch;
3396 FlagsVal |= Flag;
3397 }
3398 } else // No match for special register.
3399 return MatchOperand_NoMatch;
3400
Owen Anderson7784f1d2011-10-21 18:43:28 +00003401 // Special register without flags is NOT equivalent to "fc" flags.
3402 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3403 // two lines would enable gas compatibility at the expense of breaking
3404 // round-tripping.
3405 //
3406 // if (!FlagsVal)
3407 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003408
3409 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3410 if (SpecReg == "spsr")
3411 FlagsVal |= 16;
3412
3413 Parser.Lex(); // Eat identifier token.
3414 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3415 return MatchOperand_Success;
3416}
3417
Jim Grosbachf6c05252011-07-21 17:23:04 +00003418ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3419parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3420 int Low, int High) {
3421 const AsmToken &Tok = Parser.getTok();
3422 if (Tok.isNot(AsmToken::Identifier)) {
3423 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3424 return MatchOperand_ParseFail;
3425 }
3426 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00003427 std::string LowerOp = Op.lower();
3428 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00003429 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3430 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3431 return MatchOperand_ParseFail;
3432 }
3433 Parser.Lex(); // Eat shift type token.
3434
3435 // There must be a '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003436 if (Parser.getTok().isNot(AsmToken::Hash) &&
3437 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbachf6c05252011-07-21 17:23:04 +00003438 Error(Parser.getTok().getLoc(), "'#' expected");
3439 return MatchOperand_ParseFail;
3440 }
3441 Parser.Lex(); // Eat hash token.
3442
3443 const MCExpr *ShiftAmount;
3444 SMLoc Loc = Parser.getTok().getLoc();
3445 if (getParser().ParseExpression(ShiftAmount)) {
3446 Error(Loc, "illegal expression");
3447 return MatchOperand_ParseFail;
3448 }
3449 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3450 if (!CE) {
3451 Error(Loc, "constant expression expected");
3452 return MatchOperand_ParseFail;
3453 }
3454 int Val = CE->getValue();
3455 if (Val < Low || Val > High) {
3456 Error(Loc, "immediate value out of range");
3457 return MatchOperand_ParseFail;
3458 }
3459
3460 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3461
3462 return MatchOperand_Success;
3463}
3464
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003465ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3466parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3467 const AsmToken &Tok = Parser.getTok();
3468 SMLoc S = Tok.getLoc();
3469 if (Tok.isNot(AsmToken::Identifier)) {
3470 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3471 return MatchOperand_ParseFail;
3472 }
3473 int Val = StringSwitch<int>(Tok.getString())
3474 .Case("be", 1)
3475 .Case("le", 0)
3476 .Default(-1);
3477 Parser.Lex(); // Eat the token.
3478
3479 if (Val == -1) {
3480 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3481 return MatchOperand_ParseFail;
3482 }
3483 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3484 getContext()),
3485 S, Parser.getTok().getLoc()));
3486 return MatchOperand_Success;
3487}
3488
Jim Grosbach580f4a92011-07-25 22:20:28 +00003489/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3490/// instructions. Legal values are:
3491/// lsl #n 'n' in [0,31]
3492/// asr #n 'n' in [1,32]
3493/// n == 32 encoded as n == 0.
3494ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3495parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3496 const AsmToken &Tok = Parser.getTok();
3497 SMLoc S = Tok.getLoc();
3498 if (Tok.isNot(AsmToken::Identifier)) {
3499 Error(S, "shift operator 'asr' or 'lsl' expected");
3500 return MatchOperand_ParseFail;
3501 }
3502 StringRef ShiftName = Tok.getString();
3503 bool isASR;
3504 if (ShiftName == "lsl" || ShiftName == "LSL")
3505 isASR = false;
3506 else if (ShiftName == "asr" || ShiftName == "ASR")
3507 isASR = true;
3508 else {
3509 Error(S, "shift operator 'asr' or 'lsl' expected");
3510 return MatchOperand_ParseFail;
3511 }
3512 Parser.Lex(); // Eat the operator.
3513
3514 // A '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003515 if (Parser.getTok().isNot(AsmToken::Hash) &&
3516 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach580f4a92011-07-25 22:20:28 +00003517 Error(Parser.getTok().getLoc(), "'#' expected");
3518 return MatchOperand_ParseFail;
3519 }
3520 Parser.Lex(); // Eat hash token.
3521
3522 const MCExpr *ShiftAmount;
3523 SMLoc E = Parser.getTok().getLoc();
3524 if (getParser().ParseExpression(ShiftAmount)) {
3525 Error(E, "malformed shift expression");
3526 return MatchOperand_ParseFail;
3527 }
3528 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3529 if (!CE) {
3530 Error(E, "shift amount must be an immediate");
3531 return MatchOperand_ParseFail;
3532 }
3533
3534 int64_t Val = CE->getValue();
3535 if (isASR) {
3536 // Shift amount must be in [1,32]
3537 if (Val < 1 || Val > 32) {
3538 Error(E, "'asr' shift amount must be in range [1,32]");
3539 return MatchOperand_ParseFail;
3540 }
Owen Anderson0afa0092011-09-26 21:06:22 +00003541 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3542 if (isThumb() && Val == 32) {
3543 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3544 return MatchOperand_ParseFail;
3545 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00003546 if (Val == 32) Val = 0;
3547 } else {
3548 // Shift amount must be in [1,32]
3549 if (Val < 0 || Val > 31) {
3550 Error(E, "'lsr' shift amount must be in range [0,31]");
3551 return MatchOperand_ParseFail;
3552 }
3553 }
3554
3555 E = Parser.getTok().getLoc();
3556 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3557
3558 return MatchOperand_Success;
3559}
3560
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003561/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3562/// of instructions. Legal values are:
3563/// ror #n 'n' in {0, 8, 16, 24}
3564ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3565parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3566 const AsmToken &Tok = Parser.getTok();
3567 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00003568 if (Tok.isNot(AsmToken::Identifier))
3569 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003570 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00003571 if (ShiftName != "ror" && ShiftName != "ROR")
3572 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003573 Parser.Lex(); // Eat the operator.
3574
3575 // A '#' and a rotate amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003576 if (Parser.getTok().isNot(AsmToken::Hash) &&
3577 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003578 Error(Parser.getTok().getLoc(), "'#' expected");
3579 return MatchOperand_ParseFail;
3580 }
3581 Parser.Lex(); // Eat hash token.
3582
3583 const MCExpr *ShiftAmount;
3584 SMLoc E = Parser.getTok().getLoc();
3585 if (getParser().ParseExpression(ShiftAmount)) {
3586 Error(E, "malformed rotate expression");
3587 return MatchOperand_ParseFail;
3588 }
3589 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3590 if (!CE) {
3591 Error(E, "rotate amount must be an immediate");
3592 return MatchOperand_ParseFail;
3593 }
3594
3595 int64_t Val = CE->getValue();
3596 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3597 // normally, zero is represented in asm by omitting the rotate operand
3598 // entirely.
3599 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3600 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3601 return MatchOperand_ParseFail;
3602 }
3603
3604 E = Parser.getTok().getLoc();
3605 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3606
3607 return MatchOperand_Success;
3608}
3609
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003610ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3611parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3612 SMLoc S = Parser.getTok().getLoc();
3613 // The bitfield descriptor is really two operands, the LSB and the width.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003614 if (Parser.getTok().isNot(AsmToken::Hash) &&
3615 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003616 Error(Parser.getTok().getLoc(), "'#' expected");
3617 return MatchOperand_ParseFail;
3618 }
3619 Parser.Lex(); // Eat hash token.
3620
3621 const MCExpr *LSBExpr;
3622 SMLoc E = Parser.getTok().getLoc();
3623 if (getParser().ParseExpression(LSBExpr)) {
3624 Error(E, "malformed immediate expression");
3625 return MatchOperand_ParseFail;
3626 }
3627 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3628 if (!CE) {
3629 Error(E, "'lsb' operand must be an immediate");
3630 return MatchOperand_ParseFail;
3631 }
3632
3633 int64_t LSB = CE->getValue();
3634 // The LSB must be in the range [0,31]
3635 if (LSB < 0 || LSB > 31) {
3636 Error(E, "'lsb' operand must be in the range [0,31]");
3637 return MatchOperand_ParseFail;
3638 }
3639 E = Parser.getTok().getLoc();
3640
3641 // Expect another immediate operand.
3642 if (Parser.getTok().isNot(AsmToken::Comma)) {
3643 Error(Parser.getTok().getLoc(), "too few operands");
3644 return MatchOperand_ParseFail;
3645 }
3646 Parser.Lex(); // Eat hash token.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003647 if (Parser.getTok().isNot(AsmToken::Hash) &&
3648 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003649 Error(Parser.getTok().getLoc(), "'#' expected");
3650 return MatchOperand_ParseFail;
3651 }
3652 Parser.Lex(); // Eat hash token.
3653
3654 const MCExpr *WidthExpr;
3655 if (getParser().ParseExpression(WidthExpr)) {
3656 Error(E, "malformed immediate expression");
3657 return MatchOperand_ParseFail;
3658 }
3659 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3660 if (!CE) {
3661 Error(E, "'width' operand must be an immediate");
3662 return MatchOperand_ParseFail;
3663 }
3664
3665 int64_t Width = CE->getValue();
3666 // The LSB must be in the range [1,32-lsb]
3667 if (Width < 1 || Width > 32 - LSB) {
3668 Error(E, "'width' operand must be in the range [1,32-lsb]");
3669 return MatchOperand_ParseFail;
3670 }
3671 E = Parser.getTok().getLoc();
3672
3673 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3674
3675 return MatchOperand_Success;
3676}
3677
Jim Grosbach7ce05792011-08-03 23:50:40 +00003678ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3679parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3680 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003681 // postidx_reg := '+' register {, shift}
3682 // | '-' register {, shift}
3683 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003684
3685 // This method must return MatchOperand_NoMatch without consuming any tokens
3686 // in the case where there is no match, as other alternatives take other
3687 // parse methods.
3688 AsmToken Tok = Parser.getTok();
3689 SMLoc S = Tok.getLoc();
3690 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003691 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003692 int Reg = -1;
3693 if (Tok.is(AsmToken::Plus)) {
3694 Parser.Lex(); // Eat the '+' token.
3695 haveEaten = true;
3696 } else if (Tok.is(AsmToken::Minus)) {
3697 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003698 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003699 haveEaten = true;
3700 }
3701 if (Parser.getTok().is(AsmToken::Identifier))
3702 Reg = tryParseRegister();
3703 if (Reg == -1) {
3704 if (!haveEaten)
3705 return MatchOperand_NoMatch;
3706 Error(Parser.getTok().getLoc(), "register expected");
3707 return MatchOperand_ParseFail;
3708 }
3709 SMLoc E = Parser.getTok().getLoc();
3710
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003711 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3712 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003713 if (Parser.getTok().is(AsmToken::Comma)) {
3714 Parser.Lex(); // Eat the ','.
3715 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3716 return MatchOperand_ParseFail;
3717 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003718
3719 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3720 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003721
3722 return MatchOperand_Success;
3723}
3724
Jim Grosbach251bf252011-08-10 21:56:18 +00003725ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3726parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3727 // Check for a post-index addressing register operand. Specifically:
3728 // am3offset := '+' register
3729 // | '-' register
3730 // | register
3731 // | # imm
3732 // | # + imm
3733 // | # - imm
3734
3735 // This method must return MatchOperand_NoMatch without consuming any tokens
3736 // in the case where there is no match, as other alternatives take other
3737 // parse methods.
3738 AsmToken Tok = Parser.getTok();
3739 SMLoc S = Tok.getLoc();
3740
3741 // Do immediates first, as we always parse those if we have a '#'.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003742 if (Parser.getTok().is(AsmToken::Hash) ||
3743 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach251bf252011-08-10 21:56:18 +00003744 Parser.Lex(); // Eat the '#'.
3745 // Explicitly look for a '-', as we need to encode negative zero
3746 // differently.
3747 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3748 const MCExpr *Offset;
3749 if (getParser().ParseExpression(Offset))
3750 return MatchOperand_ParseFail;
3751 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3752 if (!CE) {
3753 Error(S, "constant expression expected");
3754 return MatchOperand_ParseFail;
3755 }
3756 SMLoc E = Tok.getLoc();
3757 // Negative zero is encoded as the flag value INT32_MIN.
3758 int32_t Val = CE->getValue();
3759 if (isNegative && Val == 0)
3760 Val = INT32_MIN;
3761
3762 Operands.push_back(
3763 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3764
3765 return MatchOperand_Success;
3766 }
3767
3768
3769 bool haveEaten = false;
3770 bool isAdd = true;
3771 int Reg = -1;
3772 if (Tok.is(AsmToken::Plus)) {
3773 Parser.Lex(); // Eat the '+' token.
3774 haveEaten = true;
3775 } else if (Tok.is(AsmToken::Minus)) {
3776 Parser.Lex(); // Eat the '-' token.
3777 isAdd = false;
3778 haveEaten = true;
3779 }
3780 if (Parser.getTok().is(AsmToken::Identifier))
3781 Reg = tryParseRegister();
3782 if (Reg == -1) {
3783 if (!haveEaten)
3784 return MatchOperand_NoMatch;
3785 Error(Parser.getTok().getLoc(), "register expected");
3786 return MatchOperand_ParseFail;
3787 }
3788 SMLoc E = Parser.getTok().getLoc();
3789
3790 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3791 0, S, E));
3792
3793 return MatchOperand_Success;
3794}
3795
Jim Grosbacha77295d2011-09-08 22:07:06 +00003796/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3797/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3798/// when they refer multiple MIOperands inside a single one.
3799bool ARMAsmParser::
3800cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3801 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3802 // Rt, Rt2
3803 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3804 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3805 // Create a writeback register dummy placeholder.
3806 Inst.addOperand(MCOperand::CreateReg(0));
3807 // addr
3808 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3809 // pred
3810 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3811 return true;
3812}
3813
3814/// cvtT2StrdPre - Convert parsed operands to MCInst.
3815/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3816/// when they refer multiple MIOperands inside a single one.
3817bool ARMAsmParser::
3818cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3819 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3820 // Create a writeback register dummy placeholder.
3821 Inst.addOperand(MCOperand::CreateReg(0));
3822 // Rt, Rt2
3823 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3824 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3825 // addr
3826 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3827 // pred
3828 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3829 return true;
3830}
3831
Jim Grosbacheeec0252011-09-08 00:39:19 +00003832/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3833/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3834/// when they refer multiple MIOperands inside a single one.
3835bool ARMAsmParser::
3836cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3837 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3838 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3839
3840 // Create a writeback register dummy placeholder.
3841 Inst.addOperand(MCOperand::CreateImm(0));
3842
3843 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3844 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3845 return true;
3846}
3847
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003848/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3849/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3850/// when they refer multiple MIOperands inside a single one.
3851bool ARMAsmParser::
3852cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3853 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3854 // Create a writeback register dummy placeholder.
3855 Inst.addOperand(MCOperand::CreateImm(0));
3856 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3857 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3858 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3859 return true;
3860}
3861
Jim Grosbach1355cf12011-07-26 17:10:22 +00003862/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003863/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3864/// when they refer multiple MIOperands inside a single one.
3865bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003866cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003867 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3868 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3869
3870 // Create a writeback register dummy placeholder.
3871 Inst.addOperand(MCOperand::CreateImm(0));
3872
Jim Grosbach7ce05792011-08-03 23:50:40 +00003873 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003874 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3875 return true;
3876}
3877
Owen Anderson9ab0f252011-08-26 20:43:14 +00003878/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3879/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3880/// when they refer multiple MIOperands inside a single one.
3881bool ARMAsmParser::
3882cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3883 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3884 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3885
3886 // Create a writeback register dummy placeholder.
3887 Inst.addOperand(MCOperand::CreateImm(0));
3888
3889 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3890 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3891 return true;
3892}
3893
3894
Jim Grosbach548340c2011-08-11 19:22:40 +00003895/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3896/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3897/// when they refer multiple MIOperands inside a single one.
3898bool ARMAsmParser::
3899cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3900 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3901 // Create a writeback register dummy placeholder.
3902 Inst.addOperand(MCOperand::CreateImm(0));
3903 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3904 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3905 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3906 return true;
3907}
3908
Jim Grosbach1355cf12011-07-26 17:10:22 +00003909/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003910/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3911/// when they refer multiple MIOperands inside a single one.
3912bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003913cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003914 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3915 // Create a writeback register dummy placeholder.
3916 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003917 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3918 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3919 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003920 return true;
3921}
3922
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003923/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3924/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3925/// when they refer multiple MIOperands inside a single one.
3926bool ARMAsmParser::
3927cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3928 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3929 // Create a writeback register dummy placeholder.
3930 Inst.addOperand(MCOperand::CreateImm(0));
3931 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3932 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3933 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3934 return true;
3935}
3936
Jim Grosbach7ce05792011-08-03 23:50:40 +00003937/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3938/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3939/// when they refer multiple MIOperands inside a single one.
3940bool ARMAsmParser::
3941cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3942 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3943 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003944 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003945 // Create a writeback register dummy placeholder.
3946 Inst.addOperand(MCOperand::CreateImm(0));
3947 // addr
3948 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3949 // offset
3950 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3951 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003952 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3953 return true;
3954}
3955
Jim Grosbach7ce05792011-08-03 23:50:40 +00003956/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003957/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3958/// when they refer multiple MIOperands inside a single one.
3959bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003960cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3961 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3962 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003963 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003964 // Create a writeback register dummy placeholder.
3965 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003966 // addr
3967 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3968 // offset
3969 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3970 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003971 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3972 return true;
3973}
3974
Jim Grosbach7ce05792011-08-03 23:50:40 +00003975/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003976/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3977/// when they refer multiple MIOperands inside a single one.
3978bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003979cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3980 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003981 // Create a writeback register dummy placeholder.
3982 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003983 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003984 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003985 // addr
3986 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3987 // offset
3988 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3989 // pred
3990 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3991 return true;
3992}
3993
3994/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3995/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3996/// when they refer multiple MIOperands inside a single one.
3997bool ARMAsmParser::
3998cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3999 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4000 // Create a writeback register dummy placeholder.
4001 Inst.addOperand(MCOperand::CreateImm(0));
4002 // Rt
4003 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
4004 // addr
4005 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
4006 // offset
4007 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
4008 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00004009 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4010 return true;
4011}
4012
Jim Grosbach2fd2b872011-08-10 20:29:19 +00004013/// cvtLdrdPre - Convert parsed operands to MCInst.
4014/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4015/// when they refer multiple MIOperands inside a single one.
4016bool ARMAsmParser::
4017cvtLdrdPre(MCInst &Inst, unsigned Opcode,
4018 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4019 // Rt, Rt2
4020 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
4021 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
4022 // Create a writeback register dummy placeholder.
4023 Inst.addOperand(MCOperand::CreateImm(0));
4024 // addr
4025 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
4026 // pred
4027 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4028 return true;
4029}
4030
Jim Grosbach14605d12011-08-11 20:28:23 +00004031/// cvtStrdPre - Convert parsed operands to MCInst.
4032/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4033/// when they refer multiple MIOperands inside a single one.
4034bool ARMAsmParser::
4035cvtStrdPre(MCInst &Inst, unsigned Opcode,
4036 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4037 // Create a writeback register dummy placeholder.
4038 Inst.addOperand(MCOperand::CreateImm(0));
4039 // Rt, Rt2
4040 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
4041 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
4042 // addr
4043 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
4044 // pred
4045 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4046 return true;
4047}
4048
Jim Grosbach623a4542011-08-10 22:42:16 +00004049/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
4050/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4051/// when they refer multiple MIOperands inside a single one.
4052bool ARMAsmParser::
4053cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
4054 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4055 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
4056 // Create a writeback register dummy placeholder.
4057 Inst.addOperand(MCOperand::CreateImm(0));
4058 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
4059 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4060 return true;
4061}
4062
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004063/// cvtThumbMultiple- Convert parsed operands to MCInst.
4064/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4065/// when they refer multiple MIOperands inside a single one.
4066bool ARMAsmParser::
4067cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
4068 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4069 // The second source operand must be the same register as the destination
4070 // operand.
4071 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00004072 (((ARMOperand*)Operands[3])->getReg() !=
4073 ((ARMOperand*)Operands[5])->getReg()) &&
4074 (((ARMOperand*)Operands[3])->getReg() !=
4075 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004076 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00004077 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004078 return false;
4079 }
4080 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
4081 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach1b332862011-11-10 22:10:12 +00004082 // If we have a three-operand form, make sure to set Rn to be the operand
4083 // that isn't the same as Rd.
4084 unsigned RegOp = 4;
4085 if (Operands.size() == 6 &&
4086 ((ARMOperand*)Operands[4])->getReg() ==
4087 ((ARMOperand*)Operands[3])->getReg())
4088 RegOp = 5;
4089 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
4090 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004091 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
4092
4093 return true;
4094}
Jim Grosbach623a4542011-08-10 22:42:16 +00004095
Jim Grosbach12431322011-10-24 22:16:58 +00004096bool ARMAsmParser::
4097cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
4098 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4099 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004100 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00004101 // Create a writeback register dummy placeholder.
4102 Inst.addOperand(MCOperand::CreateImm(0));
4103 // Vn
4104 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4105 // pred
4106 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4107 return true;
4108}
4109
4110bool ARMAsmParser::
4111cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
4112 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4113 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004114 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00004115 // Create a writeback register dummy placeholder.
4116 Inst.addOperand(MCOperand::CreateImm(0));
4117 // Vn
4118 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4119 // Vm
4120 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4121 // pred
4122 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4123 return true;
4124}
4125
Jim Grosbach4334e032011-10-31 21:50:31 +00004126bool ARMAsmParser::
4127cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
4128 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4129 // Create a writeback register dummy placeholder.
4130 Inst.addOperand(MCOperand::CreateImm(0));
4131 // Vn
4132 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4133 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004134 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00004135 // pred
4136 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4137 return true;
4138}
4139
4140bool ARMAsmParser::
4141cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
4142 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4143 // Create a writeback register dummy placeholder.
4144 Inst.addOperand(MCOperand::CreateImm(0));
4145 // Vn
4146 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4147 // Vm
4148 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4149 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004150 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00004151 // pred
4152 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4153 return true;
4154}
4155
Bill Wendlinge7176102010-11-06 22:36:58 +00004156/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004157/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00004158bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00004159parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00004160 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00004161 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00004162 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00004163 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004164 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004165
Sean Callanan18b83232010-01-19 21:44:56 +00004166 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00004167 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00004168 if (BaseRegNum == -1)
4169 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004170
Daniel Dunbar05710932011-01-18 05:34:17 +00004171 // The next token must either be a comma or a closing bracket.
4172 const AsmToken &Tok = Parser.getTok();
4173 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004174 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00004175
Jim Grosbach7ce05792011-08-03 23:50:40 +00004176 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00004177 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004178 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004179
Jim Grosbach7ce05792011-08-03 23:50:40 +00004180 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004181 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00004182
Jim Grosbachfb12f352011-09-19 18:42:21 +00004183 // If there's a pre-indexing writeback marker, '!', just add it as a token
4184 // operand. It's rather odd, but syntactically valid.
4185 if (Parser.getTok().is(AsmToken::Exclaim)) {
4186 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4187 Parser.Lex(); // Eat the '!'.
4188 }
4189
Jim Grosbach7ce05792011-08-03 23:50:40 +00004190 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004191 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004192
Jim Grosbach7ce05792011-08-03 23:50:40 +00004193 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
4194 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004195
Jim Grosbach57dcb852011-10-11 17:29:55 +00004196 // If we have a ':', it's an alignment specifier.
4197 if (Parser.getTok().is(AsmToken::Colon)) {
4198 Parser.Lex(); // Eat the ':'.
4199 E = Parser.getTok().getLoc();
4200
4201 const MCExpr *Expr;
4202 if (getParser().ParseExpression(Expr))
4203 return true;
4204
4205 // The expression has to be a constant. Memory references with relocations
4206 // don't come through here, as they use the <label> forms of the relevant
4207 // instructions.
4208 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4209 if (!CE)
4210 return Error (E, "constant expression expected");
4211
4212 unsigned Align = 0;
4213 switch (CE->getValue()) {
4214 default:
Jim Grosbacheeaf1c12011-12-19 18:31:43 +00004215 return Error(E,
4216 "alignment specifier must be 16, 32, 64, 128, or 256 bits");
4217 case 16: Align = 2; break;
4218 case 32: Align = 4; break;
Jim Grosbach57dcb852011-10-11 17:29:55 +00004219 case 64: Align = 8; break;
4220 case 128: Align = 16; break;
4221 case 256: Align = 32; break;
4222 }
4223
4224 // Now we should have the closing ']'
4225 E = Parser.getTok().getLoc();
4226 if (Parser.getTok().isNot(AsmToken::RBrac))
4227 return Error(E, "']' expected");
4228 Parser.Lex(); // Eat right bracket token.
4229
4230 // Don't worry about range checking the value here. That's handled by
4231 // the is*() predicates.
4232 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
4233 ARM_AM::no_shift, 0, Align,
4234 false, S, E));
4235
4236 // If there's a pre-indexing writeback marker, '!', just add it as a token
4237 // operand.
4238 if (Parser.getTok().is(AsmToken::Exclaim)) {
4239 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4240 Parser.Lex(); // Eat the '!'.
4241 }
4242
4243 return false;
4244 }
4245
4246 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004247 // offset. Be friendly and also accept a plain integer (without a leading
4248 // hash) for gas compatibility.
4249 if (Parser.getTok().is(AsmToken::Hash) ||
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004250 Parser.getTok().is(AsmToken::Dollar) ||
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004251 Parser.getTok().is(AsmToken::Integer)) {
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004252 if (Parser.getTok().isNot(AsmToken::Integer))
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004253 Parser.Lex(); // Eat the '#'.
Jim Grosbach7ce05792011-08-03 23:50:40 +00004254 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004255
Owen Anderson0da10cf2011-08-29 19:36:44 +00004256 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00004257 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004258 if (getParser().ParseExpression(Offset))
4259 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004260
4261 // The expression has to be a constant. Memory references with relocations
4262 // don't come through here, as they use the <label> forms of the relevant
4263 // instructions.
4264 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
4265 if (!CE)
4266 return Error (E, "constant expression expected");
4267
Owen Anderson0da10cf2011-08-29 19:36:44 +00004268 // If the constant was #-0, represent it as INT32_MIN.
4269 int32_t Val = CE->getValue();
4270 if (isNegative && Val == 0)
4271 CE = MCConstantExpr::Create(INT32_MIN, getContext());
4272
Jim Grosbach7ce05792011-08-03 23:50:40 +00004273 // Now we should have the closing ']'
4274 E = Parser.getTok().getLoc();
4275 if (Parser.getTok().isNot(AsmToken::RBrac))
4276 return Error(E, "']' expected");
4277 Parser.Lex(); // Eat right bracket token.
4278
4279 // Don't worry about range checking the value here. That's handled by
4280 // the is*() predicates.
4281 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004282 ARM_AM::no_shift, 0, 0,
4283 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00004284
4285 // If there's a pre-indexing writeback marker, '!', just add it as a token
4286 // operand.
4287 if (Parser.getTok().is(AsmToken::Exclaim)) {
4288 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4289 Parser.Lex(); // Eat the '!'.
4290 }
4291
4292 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004293 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004294
4295 // The register offset is optionally preceded by a '+' or '-'
4296 bool isNegative = false;
4297 if (Parser.getTok().is(AsmToken::Minus)) {
4298 isNegative = true;
4299 Parser.Lex(); // Eat the '-'.
4300 } else if (Parser.getTok().is(AsmToken::Plus)) {
4301 // Nothing to do.
4302 Parser.Lex(); // Eat the '+'.
4303 }
4304
4305 E = Parser.getTok().getLoc();
4306 int OffsetRegNum = tryParseRegister();
4307 if (OffsetRegNum == -1)
4308 return Error(E, "register expected");
4309
4310 // If there's a shift operator, handle it.
4311 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004312 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004313 if (Parser.getTok().is(AsmToken::Comma)) {
4314 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004315 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004316 return true;
4317 }
4318
4319 // Now we should have the closing ']'
4320 E = Parser.getTok().getLoc();
4321 if (Parser.getTok().isNot(AsmToken::RBrac))
4322 return Error(E, "']' expected");
4323 Parser.Lex(); // Eat right bracket token.
4324
4325 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004326 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00004327 S, E));
4328
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00004329 // If there's a pre-indexing writeback marker, '!', just add it as a token
4330 // operand.
4331 if (Parser.getTok().is(AsmToken::Exclaim)) {
4332 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4333 Parser.Lex(); // Eat the '!'.
4334 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004335
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004336 return false;
4337}
4338
Jim Grosbach7ce05792011-08-03 23:50:40 +00004339/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004340/// ( lsl | lsr | asr | ror ) , # shift_amount
4341/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00004342/// return true if it parses a shift otherwise it returns false.
4343bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
4344 unsigned &Amount) {
4345 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00004346 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004347 if (Tok.isNot(AsmToken::Identifier))
4348 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00004349 StringRef ShiftName = Tok.getString();
Jim Grosbachaf4edea2011-12-07 23:40:58 +00004350 if (ShiftName == "lsl" || ShiftName == "LSL" ||
4351 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson00828302011-03-18 22:50:18 +00004352 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004353 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00004354 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004355 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00004356 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004357 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00004358 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004359 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00004360 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004361 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00004362 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00004363 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004364
Jim Grosbach7ce05792011-08-03 23:50:40 +00004365 // rrx stands alone.
4366 Amount = 0;
4367 if (St != ARM_AM::rrx) {
4368 Loc = Parser.getTok().getLoc();
4369 // A '#' and a shift amount.
4370 const AsmToken &HashTok = Parser.getTok();
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004371 if (HashTok.isNot(AsmToken::Hash) &&
4372 HashTok.isNot(AsmToken::Dollar))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004373 return Error(HashTok.getLoc(), "'#' expected");
4374 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004375
Jim Grosbach7ce05792011-08-03 23:50:40 +00004376 const MCExpr *Expr;
4377 if (getParser().ParseExpression(Expr))
4378 return true;
4379 // Range check the immediate.
4380 // lsl, ror: 0 <= imm <= 31
4381 // lsr, asr: 0 <= imm <= 32
4382 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4383 if (!CE)
4384 return Error(Loc, "shift amount must be an immediate");
4385 int64_t Imm = CE->getValue();
4386 if (Imm < 0 ||
4387 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4388 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4389 return Error(Loc, "immediate shift value out of range");
4390 Amount = Imm;
4391 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004392
4393 return false;
4394}
4395
Jim Grosbach9d390362011-10-03 23:38:36 +00004396/// parseFPImm - A floating point immediate expression operand.
4397ARMAsmParser::OperandMatchResultTy ARMAsmParser::
4398parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach51222d12012-01-20 18:09:51 +00004399 // Anything that can accept a floating point constant as an operand
4400 // needs to go through here, as the regular ParseExpression is
4401 // integer only.
4402 //
4403 // This routine still creates a generic Immediate operand, containing
4404 // a bitcast of the 64-bit floating point value. The various operands
4405 // that accept floats can check whether the value is valid for them
4406 // via the standard is*() predicates.
4407
Jim Grosbach9d390362011-10-03 23:38:36 +00004408 SMLoc S = Parser.getTok().getLoc();
4409
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004410 if (Parser.getTok().isNot(AsmToken::Hash) &&
4411 Parser.getTok().isNot(AsmToken::Dollar))
Jim Grosbach9d390362011-10-03 23:38:36 +00004412 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00004413
4414 // Disambiguate the VMOV forms that can accept an FP immediate.
4415 // vmov.f32 <sreg>, #imm
4416 // vmov.f64 <dreg>, #imm
4417 // vmov.f32 <dreg>, #imm @ vector f32x2
4418 // vmov.f32 <qreg>, #imm @ vector f32x4
4419 //
4420 // There are also the NEON VMOV instructions which expect an
4421 // integer constant. Make sure we don't try to parse an FPImm
4422 // for these:
4423 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4424 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4425 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4426 TyOp->getToken() != ".f64"))
4427 return MatchOperand_NoMatch;
4428
Jim Grosbach9d390362011-10-03 23:38:36 +00004429 Parser.Lex(); // Eat the '#'.
4430
4431 // Handle negation, as that still comes through as a separate token.
4432 bool isNegative = false;
4433 if (Parser.getTok().is(AsmToken::Minus)) {
4434 isNegative = true;
4435 Parser.Lex();
4436 }
4437 const AsmToken &Tok = Parser.getTok();
Jim Grosbachae69f702012-01-19 02:47:30 +00004438 SMLoc Loc = Tok.getLoc();
Jim Grosbach9d390362011-10-03 23:38:36 +00004439 if (Tok.is(AsmToken::Real)) {
Jim Grosbach51222d12012-01-20 18:09:51 +00004440 APFloat RealVal(APFloat::IEEEsingle, Tok.getString());
Jim Grosbach9d390362011-10-03 23:38:36 +00004441 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4442 // If we had a '-' in front, toggle the sign bit.
Jim Grosbach51222d12012-01-20 18:09:51 +00004443 IntVal ^= (uint64_t)isNegative << 31;
Jim Grosbach9d390362011-10-03 23:38:36 +00004444 Parser.Lex(); // Eat the token.
Jim Grosbach51222d12012-01-20 18:09:51 +00004445 Operands.push_back(ARMOperand::CreateImm(
4446 MCConstantExpr::Create(IntVal, getContext()),
4447 S, Parser.getTok().getLoc()));
Jim Grosbach9d390362011-10-03 23:38:36 +00004448 return MatchOperand_Success;
4449 }
Jim Grosbach51222d12012-01-20 18:09:51 +00004450 // Also handle plain integers. Instructions which allow floating point
4451 // immediates also allow a raw encoded 8-bit value.
Jim Grosbach9d390362011-10-03 23:38:36 +00004452 if (Tok.is(AsmToken::Integer)) {
4453 int64_t Val = Tok.getIntVal();
4454 Parser.Lex(); // Eat the token.
4455 if (Val > 255 || Val < 0) {
Jim Grosbachae69f702012-01-19 02:47:30 +00004456 Error(Loc, "encoded floating point value out of range");
Jim Grosbach9d390362011-10-03 23:38:36 +00004457 return MatchOperand_ParseFail;
4458 }
Jim Grosbach51222d12012-01-20 18:09:51 +00004459 double RealVal = ARM_AM::getFPImmFloat(Val);
4460 Val = APFloat(APFloat::IEEEdouble, RealVal).bitcastToAPInt().getZExtValue();
4461 Operands.push_back(ARMOperand::CreateImm(
4462 MCConstantExpr::Create(Val, getContext()), S,
4463 Parser.getTok().getLoc()));
Jim Grosbach9d390362011-10-03 23:38:36 +00004464 return MatchOperand_Success;
4465 }
4466
Jim Grosbachae69f702012-01-19 02:47:30 +00004467 Error(Loc, "invalid floating point immediate");
Jim Grosbach9d390362011-10-03 23:38:36 +00004468 return MatchOperand_ParseFail;
4469}
Jim Grosbach51222d12012-01-20 18:09:51 +00004470
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004471/// Parse a arm instruction operand. For now this parses the operand regardless
4472/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004473bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004474 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00004475 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004476
4477 // Check if the current operand has a custom associated parser, if so, try to
4478 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00004479 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4480 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004481 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00004482 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4483 // there was a match, but an error occurred, in which case, just return that
4484 // the operand parsing failed.
4485 if (ResTy == MatchOperand_ParseFail)
4486 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004487
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004488 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00004489 default:
4490 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00004491 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00004492 case AsmToken::Identifier: {
Jim Grosbach1355cf12011-07-26 17:10:22 +00004493 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00004494 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00004495 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00004496 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00004497 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00004498 else if (Res == -1) // irrecoverable error
4499 return true;
Jim Grosbach3cbe43f2011-12-20 22:26:38 +00004500 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbachb84ad4a2012-03-15 21:34:14 +00004501 if (Mnemonic == "vmrs" &&
4502 Parser.getTok().getString().equals_lower("apsr_nzcv")) {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004503 S = Parser.getTok().getLoc();
4504 Parser.Lex();
Jim Grosbachb84ad4a2012-03-15 21:34:14 +00004505 Operands.push_back(ARMOperand::CreateToken("APSR_nzcv", S));
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004506 return false;
4507 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00004508
4509 // Fall though for the Identifier case that is not a register or a
4510 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00004511 }
Jim Grosbach758a5192011-10-26 21:14:08 +00004512 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00004513 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00004514 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00004515 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00004516 // This was not a register so parse other operands that start with an
4517 // identifier (like labels) as expressions and create them as immediates.
4518 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00004519 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00004520 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004521 return true;
Sean Callanan76264762010-04-02 22:27:05 +00004522 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004523 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4524 return false;
4525 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004526 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004527 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00004528 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004529 return parseRegisterList(Operands);
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004530 case AsmToken::Dollar:
Owen Anderson63553c72011-08-29 17:17:09 +00004531 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00004532 // #42 -> immediate.
Sean Callanan76264762010-04-02 22:27:05 +00004533 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004534 Parser.Lex();
Jim Grosbachb8768dc2012-04-16 21:18:46 +00004535
4536 if (Parser.getTok().isNot(AsmToken::Colon)) {
4537 bool isNegative = Parser.getTok().is(AsmToken::Minus);
4538 const MCExpr *ImmVal;
4539 if (getParser().ParseExpression(ImmVal))
4540 return true;
4541 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
4542 if (CE) {
4543 int32_t Val = CE->getValue();
4544 if (isNegative && Val == 0)
4545 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
4546 }
4547 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4548 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4549 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00004550 }
Jim Grosbachb8768dc2012-04-16 21:18:46 +00004551 // w/ a ':' after the '#', it's just like a plain ':'.
4552 // FALLTHROUGH
Owen Anderson63553c72011-08-29 17:17:09 +00004553 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004554 case AsmToken::Colon: {
4555 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00004556 // FIXME: Check it's an expression prefix,
4557 // e.g. (FOO - :lower16:BAR) isn't legal.
4558 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004559 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004560 return true;
4561
Evan Cheng75972122011-01-13 07:58:56 +00004562 const MCExpr *SubExprVal;
4563 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004564 return true;
4565
Evan Cheng75972122011-01-13 07:58:56 +00004566 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4567 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00004568 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00004569 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00004570 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004571 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004572 }
4573}
4574
Jim Grosbach1355cf12011-07-26 17:10:22 +00004575// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00004576// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004577bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00004578 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004579
4580 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00004581 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00004582 Parser.Lex(); // Eat ':'
4583
4584 if (getLexer().isNot(AsmToken::Identifier)) {
4585 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4586 return true;
4587 }
4588
4589 StringRef IDVal = Parser.getTok().getIdentifier();
4590 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00004591 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004592 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00004593 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004594 } else {
4595 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4596 return true;
4597 }
4598 Parser.Lex();
4599
4600 if (getLexer().isNot(AsmToken::Colon)) {
4601 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4602 return true;
4603 }
4604 Parser.Lex(); // Eat the last ':'
4605 return false;
4606}
4607
Daniel Dunbar352e1482011-01-11 15:59:50 +00004608/// \brief Given a mnemonic, split out possible predication code and carry
4609/// setting letters to form a canonical mnemonic and flags.
4610//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004611// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00004612// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004613StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00004614 unsigned &PredicationCode,
4615 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004616 unsigned &ProcessorIMod,
4617 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004618 PredicationCode = ARMCC::AL;
4619 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004620 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004621
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004622 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00004623 //
4624 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00004625 if ((Mnemonic == "movs" && isThumb()) ||
4626 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4627 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4628 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4629 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4630 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4631 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
Jim Grosbach68490192011-12-19 19:43:50 +00004632 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" ||
4633 Mnemonic == "fmuls")
Daniel Dunbar352e1482011-01-11 15:59:50 +00004634 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00004635
Jim Grosbach3f00e312011-07-11 17:09:57 +00004636 // First, split out any predication code. Ignore mnemonics we know aren't
4637 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00004638 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00004639 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00004640 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00004641 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00004642 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4643 .Case("eq", ARMCC::EQ)
4644 .Case("ne", ARMCC::NE)
4645 .Case("hs", ARMCC::HS)
4646 .Case("cs", ARMCC::HS)
4647 .Case("lo", ARMCC::LO)
4648 .Case("cc", ARMCC::LO)
4649 .Case("mi", ARMCC::MI)
4650 .Case("pl", ARMCC::PL)
4651 .Case("vs", ARMCC::VS)
4652 .Case("vc", ARMCC::VC)
4653 .Case("hi", ARMCC::HI)
4654 .Case("ls", ARMCC::LS)
4655 .Case("ge", ARMCC::GE)
4656 .Case("lt", ARMCC::LT)
4657 .Case("gt", ARMCC::GT)
4658 .Case("le", ARMCC::LE)
4659 .Case("al", ARMCC::AL)
4660 .Default(~0U);
4661 if (CC != ~0U) {
4662 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4663 PredicationCode = CC;
4664 }
Bill Wendling52925b62010-10-29 23:50:21 +00004665 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004666
Daniel Dunbar352e1482011-01-11 15:59:50 +00004667 // Next, determine if we have a carry setting bit. We explicitly ignore all
4668 // the instructions we know end in 's'.
4669 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00004670 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00004671 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4672 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4673 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach67ca1ad2011-12-08 00:49:29 +00004674 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach48171e72011-12-10 00:01:02 +00004675 Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
Jim Grosbach9c397892011-12-19 19:02:41 +00004676 Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" ||
Jim Grosbach6357cae2012-03-15 20:48:18 +00004677 Mnemonic == "fmuls" || Mnemonic == "fcmps" || Mnemonic == "fcmpzs" ||
Evan Cheng82509e52012-04-11 00:13:00 +00004678 Mnemonic == "vfms" || Mnemonic == "vfnms" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00004679 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004680 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4681 CarrySetting = true;
4682 }
4683
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004684 // The "cps" instruction can have a interrupt mode operand which is glued into
4685 // the mnemonic. Check if this is the case, split it and parse the imod op
4686 if (Mnemonic.startswith("cps")) {
4687 // Split out any imod code.
4688 unsigned IMod =
4689 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4690 .Case("ie", ARM_PROC::IE)
4691 .Case("id", ARM_PROC::ID)
4692 .Default(~0U);
4693 if (IMod != ~0U) {
4694 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4695 ProcessorIMod = IMod;
4696 }
4697 }
4698
Jim Grosbach89df9962011-08-26 21:43:41 +00004699 // The "it" instruction has the condition mask on the end of the mnemonic.
4700 if (Mnemonic.startswith("it")) {
4701 ITMask = Mnemonic.slice(2, Mnemonic.size());
4702 Mnemonic = Mnemonic.slice(0, 2);
4703 }
4704
Daniel Dunbar352e1482011-01-11 15:59:50 +00004705 return Mnemonic;
4706}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004707
4708/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4709/// inclusion of carry set or predication code operands.
4710//
4711// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004712void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00004713getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004714 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004715 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4716 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004717 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004718 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004719 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004720 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004721 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Evan Cheng82509e52012-04-11 00:13:00 +00004722 Mnemonic == "vfm" || Mnemonic == "vfnm" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004723 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004724 Mnemonic == "mla" || Mnemonic == "smlal" ||
4725 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004726 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004727 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004728 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004729
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004730 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4731 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4732 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4733 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004734 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4735 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004736 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004737 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4738 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4739 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004740 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4741 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004742 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004743 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004744 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004745 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004746
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004747 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004748 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004749 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004750 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004751 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004752}
4753
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004754bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4755 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004756 // FIXME: This is all horribly hacky. We really need a better way to deal
4757 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004758
4759 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4760 // another does not. Specifically, the MOVW instruction does not. So we
4761 // special case it here and remove the defaulted (non-setting) cc_out
4762 // operand if that's the instruction we're trying to match.
4763 //
4764 // We do this as post-processing of the explicit operands rather than just
4765 // conditionally adding the cc_out in the first place because we need
4766 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004767 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004768 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4769 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4770 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4771 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004772
4773 // Register-register 'add' for thumb does not have a cc_out operand
4774 // when there are only two register operands.
4775 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4776 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4777 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4778 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4779 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004780 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004781 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4782 // have to check the immediate range here since Thumb2 has a variant
4783 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004784 if (((isThumb() && Mnemonic == "add") ||
4785 (isThumbTwo() && Mnemonic == "sub")) &&
4786 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004787 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4788 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4789 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004790 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
Jim Grosbacha23ecc22012-04-10 17:31:55 +00004791 ((Mnemonic == "add" &&static_cast<ARMOperand*>(Operands[5])->isReg()) ||
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004792 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004793 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004794 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4795 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004796 // selecting via the generic "add" mnemonic, so to know that we
4797 // should remove the cc_out operand, we have to explicitly check that
4798 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004799 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4800 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004801 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4802 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4803 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4804 // Nest conditions rather than one big 'if' statement for readability.
4805 //
4806 // If either register is a high reg, it's either one of the SP
4807 // variants (handled above) or a 32-bit encoding, so we just
Jim Grosbach12a88632012-01-21 00:07:56 +00004808 // check against T3. If the second register is the PC, this is an
4809 // alternate form of ADR, which uses encoding T4, so check for that too.
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004810 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4811 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
Jim Grosbach12a88632012-01-21 00:07:56 +00004812 static_cast<ARMOperand*>(Operands[4])->getReg() != ARM::PC &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004813 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4814 return false;
4815 // If both registers are low, we're in an IT block, and the immediate is
4816 // in range, we should use encoding T1 instead, which has a cc_out.
4817 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004818 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004819 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4820 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4821 return false;
4822
4823 // Otherwise, we use encoding T4, which does not have a cc_out
4824 // operand.
4825 return true;
4826 }
4827
Jim Grosbach64944f42011-09-14 21:00:40 +00004828 // The thumb2 multiply instruction doesn't have a CCOut register, so
4829 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4830 // use the 16-bit encoding or not.
4831 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4832 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4833 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4834 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4835 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4836 // If the registers aren't low regs, the destination reg isn't the
4837 // same as one of the source regs, or the cc_out operand is zero
4838 // outside of an IT block, we have to use the 32-bit encoding, so
4839 // remove the cc_out operand.
4840 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4841 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach1de0bd12011-11-15 19:29:45 +00004842 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach64944f42011-09-14 21:00:40 +00004843 !inITBlock() ||
4844 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4845 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4846 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4847 static_cast<ARMOperand*>(Operands[4])->getReg())))
4848 return true;
4849
Jim Grosbach7f1ec952011-11-15 19:55:16 +00004850 // Also check the 'mul' syntax variant that doesn't specify an explicit
4851 // destination register.
4852 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4853 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4854 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4855 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4856 // If the registers aren't low regs or the cc_out operand is zero
4857 // outside of an IT block, we have to use the 32-bit encoding, so
4858 // remove the cc_out operand.
4859 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4860 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4861 !inITBlock()))
4862 return true;
4863
Jim Grosbach64944f42011-09-14 21:00:40 +00004864
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004865
Jim Grosbachf69c8042011-08-24 21:42:27 +00004866 // Register-register 'add/sub' for thumb does not have a cc_out operand
4867 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4868 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4869 // right, this will result in better diagnostics (which operand is off)
4870 // anyway.
4871 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4872 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004873 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4874 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
Jim Grosbacha23ecc22012-04-10 17:31:55 +00004875 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4876 (static_cast<ARMOperand*>(Operands[4])->isImm() ||
4877 (Operands.size() == 6 &&
4878 static_cast<ARMOperand*>(Operands[5])->isImm())))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004879 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004880
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004881 return false;
4882}
4883
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004884static bool isDataTypeToken(StringRef Tok) {
4885 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4886 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4887 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4888 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4889 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4890 Tok == ".f" || Tok == ".d";
4891}
4892
4893// FIXME: This bit should probably be handled via an explicit match class
4894// in the .td files that matches the suffix instead of having it be
4895// a literal string token the way it is now.
4896static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4897 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4898}
4899
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004900static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004901/// Parse an arm instruction mnemonic followed by its operands.
4902bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4903 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004904 // Apply mnemonic aliases before doing anything else, as the destination
4905 // mnemnonic may include suffices and we want to handle them normally.
4906 // The generic tblgen'erated code does this later, at the start of
4907 // MatchInstructionImpl(), but that's too late for aliases that include
4908 // any sort of suffix.
4909 unsigned AvailableFeatures = getAvailableFeatures();
4910 applyMnemonicAliases(Name, AvailableFeatures);
4911
Jim Grosbacha39cda72011-12-14 02:16:11 +00004912 // First check for the ARM-specific .req directive.
4913 if (Parser.getTok().is(AsmToken::Identifier) &&
4914 Parser.getTok().getIdentifier() == ".req") {
4915 parseDirectiveReq(Name, NameLoc);
4916 // We always return 'error' for this, as we're done with this
4917 // statement and don't need to match the 'instruction."
4918 return true;
4919 }
4920
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004921 // Create the leading tokens for the mnemonic, split by '.' characters.
4922 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004923 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004924
Daniel Dunbar352e1482011-01-11 15:59:50 +00004925 // Split out the predication code and carry setting flag from the mnemonic.
4926 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004927 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004928 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004929 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004930 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004931 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004932
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004933 // In Thumb1, only the branch (B) instruction can be predicated.
4934 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4935 Parser.EatToEndOfStatement();
4936 return Error(NameLoc, "conditional execution not supported in Thumb1");
4937 }
4938
Jim Grosbachffa32252011-07-19 19:13:28 +00004939 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4940
Jim Grosbach89df9962011-08-26 21:43:41 +00004941 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4942 // is the mask as it will be for the IT encoding if the conditional
4943 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4944 // where the conditional bit0 is zero, the instruction post-processing
4945 // will adjust the mask accordingly.
4946 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004947 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4948 if (ITMask.size() > 3) {
4949 Parser.EatToEndOfStatement();
4950 return Error(Loc, "too many conditions on IT instruction");
4951 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004952 unsigned Mask = 8;
4953 for (unsigned i = ITMask.size(); i != 0; --i) {
4954 char pos = ITMask[i - 1];
4955 if (pos != 't' && pos != 'e') {
4956 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004957 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004958 }
4959 Mask >>= 1;
4960 if (ITMask[i - 1] == 't')
4961 Mask |= 8;
4962 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004963 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004964 }
4965
Jim Grosbachffa32252011-07-19 19:13:28 +00004966 // FIXME: This is all a pretty gross hack. We should automatically handle
4967 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004968
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004969 // Next, add the CCOut and ConditionCode operands, if needed.
4970 //
4971 // For mnemonics which can ever incorporate a carry setting bit or predication
4972 // code, our matching model involves us always generating CCOut and
4973 // ConditionCode operands to match the mnemonic "as written" and then we let
4974 // the matcher deal with finding the right instruction or generating an
4975 // appropriate error.
4976 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004977 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004978
Jim Grosbach33c16a22011-07-14 22:04:21 +00004979 // If we had a carry-set on an instruction that can't do that, issue an
4980 // error.
4981 if (!CanAcceptCarrySet && CarrySetting) {
4982 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004983 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004984 "' can not set flags, but 's' suffix specified");
4985 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004986 // If we had a predication code on an instruction that can't do that, issue an
4987 // error.
4988 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4989 Parser.EatToEndOfStatement();
4990 return Error(NameLoc, "instruction '" + Mnemonic +
4991 "' is not predicable, but condition code specified");
4992 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004993
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004994 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004995 if (CanAcceptCarrySet) {
4996 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004997 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004998 Loc));
4999 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00005000
5001 // Add the predication code operand, if necessary.
5002 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005003 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
5004 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00005005 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005006 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00005007 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00005008
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00005009 // Add the processor imod operand, if necessary.
5010 if (ProcessorIMod) {
5011 Operands.push_back(ARMOperand::CreateImm(
5012 MCConstantExpr::Create(ProcessorIMod, getContext()),
5013 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00005014 }
5015
Daniel Dunbar345a9a62010-08-11 06:37:20 +00005016 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00005017 while (Next != StringRef::npos) {
5018 Start = Next;
5019 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00005020 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00005021
Jim Grosbach7aef99b2011-11-11 23:08:10 +00005022 // Some NEON instructions have an optional datatype suffix that is
5023 // completely ignored. Check for that.
5024 if (isDataTypeToken(ExtraToken) &&
5025 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
5026 continue;
5027
Jim Grosbach81d2e392011-09-07 16:06:04 +00005028 if (ExtraToken != ".n") {
5029 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
5030 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
5031 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00005032 }
5033
5034 // Read the remaining operands.
5035 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00005036 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00005037 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00005038 Parser.EatToEndOfStatement();
5039 return true;
5040 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00005041
5042 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00005043 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00005044
5045 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00005046 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00005047 Parser.EatToEndOfStatement();
5048 return true;
5049 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00005050 }
5051 }
Jim Grosbach16c74252010-10-29 14:46:02 +00005052
Chris Lattnercbf8a982010-09-11 16:18:25 +00005053 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00005054 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00005055 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00005056 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00005057 }
Bill Wendling146018f2010-11-06 21:42:12 +00005058
Chris Lattner34e53142010-09-08 05:10:46 +00005059 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00005060
Jim Grosbachd54b4e62011-08-16 21:12:37 +00005061 // Some instructions, mostly Thumb, have forms for the same mnemonic that
5062 // do and don't have a cc_out optional-def operand. With some spot-checks
5063 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00005064 // parse and adjust accordingly before actually matching. We shouldn't ever
5065 // try to remove a cc_out operand that was explicitly set on the the
5066 // mnemonic, of course (CarrySetting == true). Reason number #317 the
5067 // table driven matcher doesn't fit well with the ARM instruction set.
5068 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00005069 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
5070 Operands.erase(Operands.begin() + 1);
5071 delete Op;
5072 }
5073
Jim Grosbachcf121c32011-07-28 21:57:55 +00005074 // ARM mode 'blx' need special handling, as the register operand version
5075 // is predicable, but the label operand version is not. So, we can't rely
5076 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00005077 // a k_CondCode operand in the list. If we're trying to match the label
5078 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00005079 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
5080 static_cast<ARMOperand*>(Operands[2])->isImm()) {
5081 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
5082 Operands.erase(Operands.begin() + 1);
5083 delete Op;
5084 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00005085
5086 // The vector-compare-to-zero instructions have a literal token "#0" at
5087 // the end that comes to here as an immediate operand. Convert it to a
5088 // token to play nicely with the matcher.
5089 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
5090 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
5091 static_cast<ARMOperand*>(Operands[5])->isImm()) {
5092 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
5093 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
5094 if (CE && CE->getValue() == 0) {
5095 Operands.erase(Operands.begin() + 5);
5096 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5097 delete Op;
5098 }
5099 }
Jim Grosbach68259142011-10-03 22:30:24 +00005100 // VCMP{E} does the same thing, but with a different operand count.
5101 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
5102 static_cast<ARMOperand*>(Operands[4])->isImm()) {
5103 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
5104 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
5105 if (CE && CE->getValue() == 0) {
5106 Operands.erase(Operands.begin() + 4);
5107 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5108 delete Op;
5109 }
5110 }
Jim Grosbach934755a2011-08-22 23:47:13 +00005111 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
Jim Grosbach55b02f22011-12-13 20:50:38 +00005112 // end. Convert it to a token here. Take care not to convert those
5113 // that should hit the Thumb2 encoding.
Jim Grosbach934755a2011-08-22 23:47:13 +00005114 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
Jim Grosbach55b02f22011-12-13 20:50:38 +00005115 static_cast<ARMOperand*>(Operands[3])->isReg() &&
5116 static_cast<ARMOperand*>(Operands[4])->isReg() &&
Jim Grosbach934755a2011-08-22 23:47:13 +00005117 static_cast<ARMOperand*>(Operands[5])->isImm()) {
5118 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
5119 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
Jim Grosbach55b02f22011-12-13 20:50:38 +00005120 if (CE && CE->getValue() == 0 &&
5121 (isThumbOne() ||
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00005122 // The cc_out operand matches the IT block.
5123 ((inITBlock() != CarrySetting) &&
5124 // Neither register operand is a high register.
Jim Grosbach55b02f22011-12-13 20:50:38 +00005125 (isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00005126 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()))))){
Jim Grosbach934755a2011-08-22 23:47:13 +00005127 Operands.erase(Operands.begin() + 5);
5128 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5129 delete Op;
5130 }
5131 }
5132
Chris Lattner98986712010-01-14 22:21:20 +00005133 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005134}
5135
Jim Grosbach189610f2011-07-26 18:25:39 +00005136// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00005137
5138// return 'true' if register list contains non-low GPR registers,
5139// 'false' otherwise. If Reg is in the register list or is HiReg, set
5140// 'containsReg' to true.
5141static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
5142 unsigned HiReg, bool &containsReg) {
5143 containsReg = false;
5144 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5145 unsigned OpReg = Inst.getOperand(i).getReg();
5146 if (OpReg == Reg)
5147 containsReg = true;
5148 // Anything other than a low register isn't legal here.
5149 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
5150 return true;
5151 }
5152 return false;
5153}
5154
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005155// Check if the specified regisgter is in the register list of the inst,
5156// starting at the indicated operand number.
5157static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
5158 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5159 unsigned OpReg = Inst.getOperand(i).getReg();
5160 if (OpReg == Reg)
5161 return true;
5162 }
5163 return false;
5164}
5165
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005166// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
5167// the ARMInsts array) instead. Getting that here requires awkward
5168// API changes, though. Better way?
5169namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005170extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005171}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005172static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005173 return ARMInsts[Opcode];
5174}
5175
Jim Grosbach189610f2011-07-26 18:25:39 +00005176// FIXME: We would really like to be able to tablegen'erate this.
5177bool ARMAsmParser::
5178validateInstruction(MCInst &Inst,
5179 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005180 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005181 SMLoc Loc = Operands[0]->getStartLoc();
5182 // Check the IT block state first.
Jim Grosbach74423e32012-01-25 19:52:01 +00005183 // NOTE: BKPT instruction has the interesting property of being
5184 // allowed in IT blocks, but not being predicable. It just always
Owen Andersonb6b7f512011-09-13 17:59:19 +00005185 // executes.
Jim Grosbach74423e32012-01-25 19:52:01 +00005186 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT &&
5187 Inst.getOpcode() != ARM::BKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005188 unsigned bit = 1;
5189 if (ITState.FirstCond)
5190 ITState.FirstCond = false;
5191 else
Jim Grosbacha1109882011-09-02 23:22:08 +00005192 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005193 // The instruction must be predicable.
5194 if (!MCID.isPredicable())
5195 return Error(Loc, "instructions in IT block must be predicable");
5196 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
5197 unsigned ITCond = bit ? ITState.Cond :
5198 ARMCC::getOppositeCondition(ITState.Cond);
5199 if (Cond != ITCond) {
5200 // Find the condition code Operand to get its SMLoc information.
5201 SMLoc CondLoc;
5202 for (unsigned i = 1; i < Operands.size(); ++i)
5203 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
5204 CondLoc = Operands[i]->getStartLoc();
5205 return Error(CondLoc, "incorrect condition in IT block; got '" +
5206 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
5207 "', but expected '" +
5208 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
5209 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00005210 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005211 } else if (isThumbTwo() && MCID.isPredicable() &&
5212 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005213 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
5214 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005215 return Error(Loc, "predicated instructions must be in IT block");
5216
Jim Grosbach189610f2011-07-26 18:25:39 +00005217 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00005218 case ARM::LDRD:
5219 case ARM::LDRD_PRE:
5220 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005221 case ARM::LDREXD: {
5222 // Rt2 must be Rt + 1.
5223 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5224 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5225 if (Rt2 != Rt + 1)
5226 return Error(Operands[3]->getStartLoc(),
5227 "destination operands must be sequential");
5228 return false;
5229 }
Jim Grosbach14605d12011-08-11 20:28:23 +00005230 case ARM::STRD: {
5231 // Rt2 must be Rt + 1.
5232 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5233 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5234 if (Rt2 != Rt + 1)
5235 return Error(Operands[3]->getStartLoc(),
5236 "source operands must be sequential");
5237 return false;
5238 }
Jim Grosbach53642c52011-08-10 20:49:18 +00005239 case ARM::STRD_PRE:
5240 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005241 case ARM::STREXD: {
5242 // Rt2 must be Rt + 1.
5243 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5244 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
5245 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00005246 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00005247 "source operands must be sequential");
5248 return false;
5249 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005250 case ARM::SBFX:
5251 case ARM::UBFX: {
5252 // width must be in range [1, 32-lsb]
5253 unsigned lsb = Inst.getOperand(2).getImm();
5254 unsigned widthm1 = Inst.getOperand(3).getImm();
5255 if (widthm1 >= 32 - lsb)
5256 return Error(Operands[5]->getStartLoc(),
5257 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00005258 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005259 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005260 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005261 // If we're parsing Thumb2, the .w variant is available and handles
5262 // most cases that are normally illegal for a Thumb1 LDM
5263 // instruction. We'll make the transformation in processInstruction()
5264 // if necessary.
5265 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005266 // Thumb LDM instructions are writeback iff the base register is not
5267 // in the register list.
5268 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005269 bool hasWritebackToken =
5270 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5271 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00005272 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005273 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005274 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
5275 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005276 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005277 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005278 return Error(Operands[2]->getStartLoc(),
5279 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005280 // If we should not have writeback, there must not be a '!'. This is
5281 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00005282 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005283 return Error(Operands[3]->getStartLoc(),
5284 "writeback operator '!' not allowed when base register "
5285 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005286
5287 break;
5288 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005289 case ARM::t2LDMIA_UPD: {
5290 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
5291 return Error(Operands[4]->getStartLoc(),
5292 "writeback operator '!' not allowed when base register "
5293 "in register list");
5294 break;
5295 }
Jim Grosbach54026372011-11-10 23:17:11 +00005296 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
5297 // so only issue a diagnostic for thumb1. The instructions will be
5298 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005299 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005300 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005301 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
5302 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005303 return Error(Operands[2]->getStartLoc(),
5304 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005305 break;
5306 }
5307 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005308 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005309 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
5310 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005311 return Error(Operands[2]->getStartLoc(),
5312 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005313 break;
5314 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00005315 case ARM::tSTMIA_UPD: {
5316 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00005317 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00005318 return Error(Operands[4]->getStartLoc(),
5319 "registers must be in range r0-r7");
5320 break;
5321 }
Jim Grosbacha9cc08f2012-04-27 23:51:36 +00005322 case ARM::tADDrSP: {
5323 // If the non-SP source operand and the destination operand are not the
5324 // same, we need thumb2 (for the wide encoding), or we have an error.
5325 if (!isThumbTwo() &&
5326 Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg()) {
5327 return Error(Operands[4]->getStartLoc(),
5328 "source register must be the same as destination");
5329 }
5330 break;
5331 }
Jim Grosbach189610f2011-07-26 18:25:39 +00005332 }
5333
5334 return false;
5335}
5336
Jim Grosbachd7433e22012-01-23 23:45:44 +00005337static unsigned getRealVSTOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach84defb52011-12-02 22:34:51 +00005338 switch(Opc) {
Craig Topperbc219812012-02-07 02:50:20 +00005339 default: llvm_unreachable("unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005340 // VST1LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005341 case ARM::VST1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
5342 case ARM::VST1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
5343 case ARM::VST1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
5344 case ARM::VST1LNdWB_register_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
5345 case ARM::VST1LNdWB_register_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
5346 case ARM::VST1LNdWB_register_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
5347 case ARM::VST1LNdAsm_8: Spacing = 1; return ARM::VST1LNd8;
5348 case ARM::VST1LNdAsm_16: Spacing = 1; return ARM::VST1LNd16;
5349 case ARM::VST1LNdAsm_32: Spacing = 1; return ARM::VST1LNd32;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005350
5351 // VST2LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005352 case ARM::VST2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
5353 case ARM::VST2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
5354 case ARM::VST2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
5355 case ARM::VST2LNqWB_fixed_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
5356 case ARM::VST2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005357
Jim Grosbach7945ead2012-01-24 00:43:12 +00005358 case ARM::VST2LNdWB_register_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
5359 case ARM::VST2LNdWB_register_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
5360 case ARM::VST2LNdWB_register_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
5361 case ARM::VST2LNqWB_register_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
5362 case ARM::VST2LNqWB_register_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005363
Jim Grosbach7945ead2012-01-24 00:43:12 +00005364 case ARM::VST2LNdAsm_8: Spacing = 1; return ARM::VST2LNd8;
5365 case ARM::VST2LNdAsm_16: Spacing = 1; return ARM::VST2LNd16;
5366 case ARM::VST2LNdAsm_32: Spacing = 1; return ARM::VST2LNd32;
5367 case ARM::VST2LNqAsm_16: Spacing = 2; return ARM::VST2LNq16;
5368 case ARM::VST2LNqAsm_32: Spacing = 2; return ARM::VST2LNq32;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005369
Jim Grosbach4adb1822012-01-24 00:07:41 +00005370 // VST3LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005371 case ARM::VST3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
5372 case ARM::VST3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
5373 case ARM::VST3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
5374 case ARM::VST3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNq16_UPD;
5375 case ARM::VST3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
5376 case ARM::VST3LNdWB_register_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
5377 case ARM::VST3LNdWB_register_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
5378 case ARM::VST3LNdWB_register_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
5379 case ARM::VST3LNqWB_register_Asm_16: Spacing = 2; return ARM::VST3LNq16_UPD;
5380 case ARM::VST3LNqWB_register_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
5381 case ARM::VST3LNdAsm_8: Spacing = 1; return ARM::VST3LNd8;
5382 case ARM::VST3LNdAsm_16: Spacing = 1; return ARM::VST3LNd16;
5383 case ARM::VST3LNdAsm_32: Spacing = 1; return ARM::VST3LNd32;
5384 case ARM::VST3LNqAsm_16: Spacing = 2; return ARM::VST3LNq16;
5385 case ARM::VST3LNqAsm_32: Spacing = 2; return ARM::VST3LNq32;
Jim Grosbach4adb1822012-01-24 00:07:41 +00005386
Jim Grosbachd7433e22012-01-23 23:45:44 +00005387 // VST3
Jim Grosbach7945ead2012-01-24 00:43:12 +00005388 case ARM::VST3dWB_fixed_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
5389 case ARM::VST3dWB_fixed_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
5390 case ARM::VST3dWB_fixed_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
5391 case ARM::VST3qWB_fixed_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
5392 case ARM::VST3qWB_fixed_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
5393 case ARM::VST3qWB_fixed_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
5394 case ARM::VST3dWB_register_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
5395 case ARM::VST3dWB_register_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
5396 case ARM::VST3dWB_register_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
5397 case ARM::VST3qWB_register_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
5398 case ARM::VST3qWB_register_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
5399 case ARM::VST3qWB_register_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
5400 case ARM::VST3dAsm_8: Spacing = 1; return ARM::VST3d8;
5401 case ARM::VST3dAsm_16: Spacing = 1; return ARM::VST3d16;
5402 case ARM::VST3dAsm_32: Spacing = 1; return ARM::VST3d32;
5403 case ARM::VST3qAsm_8: Spacing = 2; return ARM::VST3q8;
5404 case ARM::VST3qAsm_16: Spacing = 2; return ARM::VST3q16;
5405 case ARM::VST3qAsm_32: Spacing = 2; return ARM::VST3q32;
Jim Grosbach539aab72012-01-24 00:58:13 +00005406
Jim Grosbach88a54de2012-01-24 18:53:13 +00005407 // VST4LN
5408 case ARM::VST4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD;
5409 case ARM::VST4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD;
5410 case ARM::VST4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD;
5411 case ARM::VST4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNq16_UPD;
5412 case ARM::VST4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD;
5413 case ARM::VST4LNdWB_register_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD;
5414 case ARM::VST4LNdWB_register_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD;
5415 case ARM::VST4LNdWB_register_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD;
5416 case ARM::VST4LNqWB_register_Asm_16: Spacing = 2; return ARM::VST4LNq16_UPD;
5417 case ARM::VST4LNqWB_register_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD;
5418 case ARM::VST4LNdAsm_8: Spacing = 1; return ARM::VST4LNd8;
5419 case ARM::VST4LNdAsm_16: Spacing = 1; return ARM::VST4LNd16;
5420 case ARM::VST4LNdAsm_32: Spacing = 1; return ARM::VST4LNd32;
5421 case ARM::VST4LNqAsm_16: Spacing = 2; return ARM::VST4LNq16;
5422 case ARM::VST4LNqAsm_32: Spacing = 2; return ARM::VST4LNq32;
5423
Jim Grosbach539aab72012-01-24 00:58:13 +00005424 // VST4
5425 case ARM::VST4dWB_fixed_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
5426 case ARM::VST4dWB_fixed_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
5427 case ARM::VST4dWB_fixed_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
5428 case ARM::VST4qWB_fixed_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
5429 case ARM::VST4qWB_fixed_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
5430 case ARM::VST4qWB_fixed_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
5431 case ARM::VST4dWB_register_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
5432 case ARM::VST4dWB_register_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
5433 case ARM::VST4dWB_register_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
5434 case ARM::VST4qWB_register_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
5435 case ARM::VST4qWB_register_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
5436 case ARM::VST4qWB_register_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
5437 case ARM::VST4dAsm_8: Spacing = 1; return ARM::VST4d8;
5438 case ARM::VST4dAsm_16: Spacing = 1; return ARM::VST4d16;
5439 case ARM::VST4dAsm_32: Spacing = 1; return ARM::VST4d32;
5440 case ARM::VST4qAsm_8: Spacing = 2; return ARM::VST4q8;
5441 case ARM::VST4qAsm_16: Spacing = 2; return ARM::VST4q16;
5442 case ARM::VST4qAsm_32: Spacing = 2; return ARM::VST4q32;
Jim Grosbach84defb52011-12-02 22:34:51 +00005443 }
5444}
5445
Jim Grosbachd7433e22012-01-23 23:45:44 +00005446static unsigned getRealVLDOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005447 switch(Opc) {
Craig Topperbc219812012-02-07 02:50:20 +00005448 default: llvm_unreachable("unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005449 // VLD1LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005450 case ARM::VLD1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
5451 case ARM::VLD1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
5452 case ARM::VLD1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
5453 case ARM::VLD1LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
5454 case ARM::VLD1LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
5455 case ARM::VLD1LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
5456 case ARM::VLD1LNdAsm_8: Spacing = 1; return ARM::VLD1LNd8;
5457 case ARM::VLD1LNdAsm_16: Spacing = 1; return ARM::VLD1LNd16;
5458 case ARM::VLD1LNdAsm_32: Spacing = 1; return ARM::VLD1LNd32;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005459
5460 // VLD2LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005461 case ARM::VLD2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
5462 case ARM::VLD2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
5463 case ARM::VLD2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
5464 case ARM::VLD2LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNq16_UPD;
5465 case ARM::VLD2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
5466 case ARM::VLD2LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
5467 case ARM::VLD2LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
5468 case ARM::VLD2LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
5469 case ARM::VLD2LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD2LNq16_UPD;
5470 case ARM::VLD2LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
5471 case ARM::VLD2LNdAsm_8: Spacing = 1; return ARM::VLD2LNd8;
5472 case ARM::VLD2LNdAsm_16: Spacing = 1; return ARM::VLD2LNd16;
5473 case ARM::VLD2LNdAsm_32: Spacing = 1; return ARM::VLD2LNd32;
5474 case ARM::VLD2LNqAsm_16: Spacing = 2; return ARM::VLD2LNq16;
5475 case ARM::VLD2LNqAsm_32: Spacing = 2; return ARM::VLD2LNq32;
Jim Grosbach3a678af2012-01-23 21:53:26 +00005476
Jim Grosbach5e59f7e2012-01-24 23:47:04 +00005477 // VLD3DUP
5478 case ARM::VLD3DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD;
5479 case ARM::VLD3DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD;
5480 case ARM::VLD3DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD;
5481 case ARM::VLD3DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPq8_UPD;
5482 case ARM::VLD3DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPq16_UPD;
5483 case ARM::VLD3DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD;
5484 case ARM::VLD3DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD;
5485 case ARM::VLD3DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD;
5486 case ARM::VLD3DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD;
5487 case ARM::VLD3DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD3DUPq8_UPD;
5488 case ARM::VLD3DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD3DUPq16_UPD;
5489 case ARM::VLD3DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD;
5490 case ARM::VLD3DUPdAsm_8: Spacing = 1; return ARM::VLD3DUPd8;
5491 case ARM::VLD3DUPdAsm_16: Spacing = 1; return ARM::VLD3DUPd16;
5492 case ARM::VLD3DUPdAsm_32: Spacing = 1; return ARM::VLD3DUPd32;
5493 case ARM::VLD3DUPqAsm_8: Spacing = 2; return ARM::VLD3DUPq8;
5494 case ARM::VLD3DUPqAsm_16: Spacing = 2; return ARM::VLD3DUPq16;
5495 case ARM::VLD3DUPqAsm_32: Spacing = 2; return ARM::VLD3DUPq32;
5496
Jim Grosbach3a678af2012-01-23 21:53:26 +00005497 // VLD3LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005498 case ARM::VLD3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
5499 case ARM::VLD3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
5500 case ARM::VLD3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
5501 case ARM::VLD3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNq16_UPD;
5502 case ARM::VLD3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
5503 case ARM::VLD3LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
5504 case ARM::VLD3LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
5505 case ARM::VLD3LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
5506 case ARM::VLD3LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD3LNq16_UPD;
5507 case ARM::VLD3LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
5508 case ARM::VLD3LNdAsm_8: Spacing = 1; return ARM::VLD3LNd8;
5509 case ARM::VLD3LNdAsm_16: Spacing = 1; return ARM::VLD3LNd16;
5510 case ARM::VLD3LNdAsm_32: Spacing = 1; return ARM::VLD3LNd32;
5511 case ARM::VLD3LNqAsm_16: Spacing = 2; return ARM::VLD3LNq16;
5512 case ARM::VLD3LNqAsm_32: Spacing = 2; return ARM::VLD3LNq32;
Jim Grosbachc387fc62012-01-23 23:20:46 +00005513
5514 // VLD3
Jim Grosbach7945ead2012-01-24 00:43:12 +00005515 case ARM::VLD3dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
5516 case ARM::VLD3dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
5517 case ARM::VLD3dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
5518 case ARM::VLD3qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
5519 case ARM::VLD3qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
5520 case ARM::VLD3qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
5521 case ARM::VLD3dWB_register_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
5522 case ARM::VLD3dWB_register_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
5523 case ARM::VLD3dWB_register_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
5524 case ARM::VLD3qWB_register_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
5525 case ARM::VLD3qWB_register_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
5526 case ARM::VLD3qWB_register_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
5527 case ARM::VLD3dAsm_8: Spacing = 1; return ARM::VLD3d8;
5528 case ARM::VLD3dAsm_16: Spacing = 1; return ARM::VLD3d16;
5529 case ARM::VLD3dAsm_32: Spacing = 1; return ARM::VLD3d32;
5530 case ARM::VLD3qAsm_8: Spacing = 2; return ARM::VLD3q8;
5531 case ARM::VLD3qAsm_16: Spacing = 2; return ARM::VLD3q16;
5532 case ARM::VLD3qAsm_32: Spacing = 2; return ARM::VLD3q32;
Jim Grosbach8abe7e32012-01-24 00:43:17 +00005533
Jim Grosbache983a132012-01-24 18:37:25 +00005534 // VLD4LN
5535 case ARM::VLD4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD;
5536 case ARM::VLD4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
5537 case ARM::VLD4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
5538 case ARM::VLD4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNq16_UPD;
5539 case ARM::VLD4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
5540 case ARM::VLD4LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD;
5541 case ARM::VLD4LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
5542 case ARM::VLD4LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
5543 case ARM::VLD4LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD4LNq16_UPD;
5544 case ARM::VLD4LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
5545 case ARM::VLD4LNdAsm_8: Spacing = 1; return ARM::VLD4LNd8;
5546 case ARM::VLD4LNdAsm_16: Spacing = 1; return ARM::VLD4LNd16;
5547 case ARM::VLD4LNdAsm_32: Spacing = 1; return ARM::VLD4LNd32;
5548 case ARM::VLD4LNqAsm_16: Spacing = 2; return ARM::VLD4LNq16;
5549 case ARM::VLD4LNqAsm_32: Spacing = 2; return ARM::VLD4LNq32;
5550
Jim Grosbacha57a36a2012-01-25 00:01:08 +00005551 // VLD4DUP
5552 case ARM::VLD4DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD;
5553 case ARM::VLD4DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD;
5554 case ARM::VLD4DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD;
5555 case ARM::VLD4DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPq8_UPD;
5556 case ARM::VLD4DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPq16_UPD;
5557 case ARM::VLD4DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD;
5558 case ARM::VLD4DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD;
5559 case ARM::VLD4DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD;
5560 case ARM::VLD4DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD;
5561 case ARM::VLD4DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD4DUPq8_UPD;
5562 case ARM::VLD4DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD4DUPq16_UPD;
5563 case ARM::VLD4DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD;
5564 case ARM::VLD4DUPdAsm_8: Spacing = 1; return ARM::VLD4DUPd8;
5565 case ARM::VLD4DUPdAsm_16: Spacing = 1; return ARM::VLD4DUPd16;
5566 case ARM::VLD4DUPdAsm_32: Spacing = 1; return ARM::VLD4DUPd32;
5567 case ARM::VLD4DUPqAsm_8: Spacing = 2; return ARM::VLD4DUPq8;
5568 case ARM::VLD4DUPqAsm_16: Spacing = 2; return ARM::VLD4DUPq16;
5569 case ARM::VLD4DUPqAsm_32: Spacing = 2; return ARM::VLD4DUPq32;
5570
Jim Grosbach8abe7e32012-01-24 00:43:17 +00005571 // VLD4
5572 case ARM::VLD4dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
5573 case ARM::VLD4dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
5574 case ARM::VLD4dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
5575 case ARM::VLD4qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
5576 case ARM::VLD4qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
5577 case ARM::VLD4qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
5578 case ARM::VLD4dWB_register_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
5579 case ARM::VLD4dWB_register_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
5580 case ARM::VLD4dWB_register_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
5581 case ARM::VLD4qWB_register_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
5582 case ARM::VLD4qWB_register_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
5583 case ARM::VLD4qWB_register_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
5584 case ARM::VLD4dAsm_8: Spacing = 1; return ARM::VLD4d8;
5585 case ARM::VLD4dAsm_16: Spacing = 1; return ARM::VLD4d16;
5586 case ARM::VLD4dAsm_32: Spacing = 1; return ARM::VLD4d32;
5587 case ARM::VLD4qAsm_8: Spacing = 2; return ARM::VLD4q8;
5588 case ARM::VLD4qAsm_16: Spacing = 2; return ARM::VLD4q16;
5589 case ARM::VLD4qAsm_32: Spacing = 2; return ARM::VLD4q32;
Jim Grosbach7636bf62011-12-02 00:35:16 +00005590 }
5591}
5592
Jim Grosbach83ec8772011-11-10 23:42:14 +00005593bool ARMAsmParser::
Jim Grosbachf8fce712011-08-11 17:35:48 +00005594processInstruction(MCInst &Inst,
5595 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5596 switch (Inst.getOpcode()) {
Jim Grosbach0b4c6732012-01-18 22:46:46 +00005597 // Aliases for alternate PC+imm syntax of LDR instructions.
5598 case ARM::t2LDRpcrel:
5599 Inst.setOpcode(ARM::t2LDRpci);
5600 return true;
5601 case ARM::t2LDRBpcrel:
5602 Inst.setOpcode(ARM::t2LDRBpci);
5603 return true;
5604 case ARM::t2LDRHpcrel:
5605 Inst.setOpcode(ARM::t2LDRHpci);
5606 return true;
5607 case ARM::t2LDRSBpcrel:
5608 Inst.setOpcode(ARM::t2LDRSBpci);
5609 return true;
5610 case ARM::t2LDRSHpcrel:
5611 Inst.setOpcode(ARM::t2LDRSHpci);
5612 return true;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005613 // Handle NEON VST complex aliases.
Jim Grosbach8b31f952012-01-23 19:39:08 +00005614 case ARM::VST1LNdWB_register_Asm_8:
5615 case ARM::VST1LNdWB_register_Asm_16:
5616 case ARM::VST1LNdWB_register_Asm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005617 MCInst TmpInst;
5618 // Shuffle the operands around so the lane index operand is in the
5619 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005620 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005621 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005622 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5623 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5624 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5625 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5626 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5627 TmpInst.addOperand(Inst.getOperand(1)); // lane
5628 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5629 TmpInst.addOperand(Inst.getOperand(6));
5630 Inst = TmpInst;
5631 return true;
5632 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005633
Jim Grosbach8b31f952012-01-23 19:39:08 +00005634 case ARM::VST2LNdWB_register_Asm_8:
5635 case ARM::VST2LNdWB_register_Asm_16:
5636 case ARM::VST2LNdWB_register_Asm_32:
5637 case ARM::VST2LNqWB_register_Asm_16:
5638 case ARM::VST2LNqWB_register_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005639 MCInst TmpInst;
5640 // Shuffle the operands around so the lane index operand is in the
5641 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005642 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005643 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005644 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5645 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5646 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5647 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5648 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005649 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5650 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005651 TmpInst.addOperand(Inst.getOperand(1)); // lane
5652 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5653 TmpInst.addOperand(Inst.getOperand(6));
5654 Inst = TmpInst;
5655 return true;
5656 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005657
5658 case ARM::VST3LNdWB_register_Asm_8:
5659 case ARM::VST3LNdWB_register_Asm_16:
5660 case ARM::VST3LNdWB_register_Asm_32:
5661 case ARM::VST3LNqWB_register_Asm_16:
5662 case ARM::VST3LNqWB_register_Asm_32: {
5663 MCInst TmpInst;
5664 // Shuffle the operands around so the lane index operand is in the
5665 // right place.
5666 unsigned Spacing;
5667 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5668 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5669 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5670 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5671 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5672 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5673 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5674 Spacing));
5675 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5676 Spacing * 2));
5677 TmpInst.addOperand(Inst.getOperand(1)); // lane
5678 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5679 TmpInst.addOperand(Inst.getOperand(6));
5680 Inst = TmpInst;
5681 return true;
5682 }
5683
Jim Grosbach88a54de2012-01-24 18:53:13 +00005684 case ARM::VST4LNdWB_register_Asm_8:
5685 case ARM::VST4LNdWB_register_Asm_16:
5686 case ARM::VST4LNdWB_register_Asm_32:
5687 case ARM::VST4LNqWB_register_Asm_16:
5688 case ARM::VST4LNqWB_register_Asm_32: {
5689 MCInst TmpInst;
5690 // Shuffle the operands around so the lane index operand is in the
5691 // right place.
5692 unsigned Spacing;
5693 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5694 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5695 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5696 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5697 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5698 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5699 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5700 Spacing));
5701 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5702 Spacing * 2));
5703 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5704 Spacing * 3));
5705 TmpInst.addOperand(Inst.getOperand(1)); // lane
5706 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5707 TmpInst.addOperand(Inst.getOperand(6));
5708 Inst = TmpInst;
5709 return true;
5710 }
5711
Jim Grosbach8b31f952012-01-23 19:39:08 +00005712 case ARM::VST1LNdWB_fixed_Asm_8:
5713 case ARM::VST1LNdWB_fixed_Asm_16:
5714 case ARM::VST1LNdWB_fixed_Asm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005715 MCInst TmpInst;
5716 // Shuffle the operands around so the lane index operand is in the
5717 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005718 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005719 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005720 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5721 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5722 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5723 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5724 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5725 TmpInst.addOperand(Inst.getOperand(1)); // lane
5726 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5727 TmpInst.addOperand(Inst.getOperand(5));
5728 Inst = TmpInst;
5729 return true;
5730 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005731
Jim Grosbach8b31f952012-01-23 19:39:08 +00005732 case ARM::VST2LNdWB_fixed_Asm_8:
5733 case ARM::VST2LNdWB_fixed_Asm_16:
5734 case ARM::VST2LNdWB_fixed_Asm_32:
5735 case ARM::VST2LNqWB_fixed_Asm_16:
5736 case ARM::VST2LNqWB_fixed_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005737 MCInst TmpInst;
5738 // Shuffle the operands around so the lane index operand is in the
5739 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005740 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005741 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005742 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5743 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5744 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5745 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5746 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005747 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5748 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005749 TmpInst.addOperand(Inst.getOperand(1)); // lane
5750 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5751 TmpInst.addOperand(Inst.getOperand(5));
5752 Inst = TmpInst;
5753 return true;
5754 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005755
5756 case ARM::VST3LNdWB_fixed_Asm_8:
5757 case ARM::VST3LNdWB_fixed_Asm_16:
5758 case ARM::VST3LNdWB_fixed_Asm_32:
5759 case ARM::VST3LNqWB_fixed_Asm_16:
5760 case ARM::VST3LNqWB_fixed_Asm_32: {
5761 MCInst TmpInst;
5762 // Shuffle the operands around so the lane index operand is in the
5763 // right place.
5764 unsigned Spacing;
5765 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5766 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5767 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5768 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5769 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5770 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5771 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5772 Spacing));
5773 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5774 Spacing * 2));
5775 TmpInst.addOperand(Inst.getOperand(1)); // lane
5776 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5777 TmpInst.addOperand(Inst.getOperand(5));
5778 Inst = TmpInst;
5779 return true;
5780 }
5781
Jim Grosbach88a54de2012-01-24 18:53:13 +00005782 case ARM::VST4LNdWB_fixed_Asm_8:
5783 case ARM::VST4LNdWB_fixed_Asm_16:
5784 case ARM::VST4LNdWB_fixed_Asm_32:
5785 case ARM::VST4LNqWB_fixed_Asm_16:
5786 case ARM::VST4LNqWB_fixed_Asm_32: {
5787 MCInst TmpInst;
5788 // Shuffle the operands around so the lane index operand is in the
5789 // right place.
5790 unsigned Spacing;
5791 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5792 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5793 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5794 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5795 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5796 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5797 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5798 Spacing));
5799 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5800 Spacing * 2));
5801 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5802 Spacing * 3));
5803 TmpInst.addOperand(Inst.getOperand(1)); // lane
5804 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5805 TmpInst.addOperand(Inst.getOperand(5));
5806 Inst = TmpInst;
5807 return true;
5808 }
5809
Jim Grosbach8b31f952012-01-23 19:39:08 +00005810 case ARM::VST1LNdAsm_8:
5811 case ARM::VST1LNdAsm_16:
5812 case ARM::VST1LNdAsm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005813 MCInst TmpInst;
5814 // Shuffle the operands around so the lane index operand is in the
5815 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005816 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005817 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005818 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5819 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5820 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5821 TmpInst.addOperand(Inst.getOperand(1)); // lane
5822 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5823 TmpInst.addOperand(Inst.getOperand(5));
5824 Inst = TmpInst;
5825 return true;
5826 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005827
Jim Grosbach8b31f952012-01-23 19:39:08 +00005828 case ARM::VST2LNdAsm_8:
5829 case ARM::VST2LNdAsm_16:
5830 case ARM::VST2LNdAsm_32:
5831 case ARM::VST2LNqAsm_16:
5832 case ARM::VST2LNqAsm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005833 MCInst TmpInst;
5834 // Shuffle the operands around so the lane index operand is in the
5835 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005836 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005837 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005838 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5839 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5840 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005841 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5842 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005843 TmpInst.addOperand(Inst.getOperand(1)); // lane
5844 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5845 TmpInst.addOperand(Inst.getOperand(5));
5846 Inst = TmpInst;
5847 return true;
5848 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005849
5850 case ARM::VST3LNdAsm_8:
5851 case ARM::VST3LNdAsm_16:
5852 case ARM::VST3LNdAsm_32:
5853 case ARM::VST3LNqAsm_16:
5854 case ARM::VST3LNqAsm_32: {
5855 MCInst TmpInst;
5856 // Shuffle the operands around so the lane index operand is in the
5857 // right place.
5858 unsigned Spacing;
5859 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5860 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5861 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5862 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5863 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5864 Spacing));
5865 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5866 Spacing * 2));
5867 TmpInst.addOperand(Inst.getOperand(1)); // lane
5868 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5869 TmpInst.addOperand(Inst.getOperand(5));
5870 Inst = TmpInst;
5871 return true;
5872 }
5873
Jim Grosbach88a54de2012-01-24 18:53:13 +00005874 case ARM::VST4LNdAsm_8:
5875 case ARM::VST4LNdAsm_16:
5876 case ARM::VST4LNdAsm_32:
5877 case ARM::VST4LNqAsm_16:
5878 case ARM::VST4LNqAsm_32: {
5879 MCInst TmpInst;
5880 // Shuffle the operands around so the lane index operand is in the
5881 // right place.
5882 unsigned Spacing;
5883 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5884 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5885 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5886 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5887 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5888 Spacing));
5889 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5890 Spacing * 2));
5891 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5892 Spacing * 3));
5893 TmpInst.addOperand(Inst.getOperand(1)); // lane
5894 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5895 TmpInst.addOperand(Inst.getOperand(5));
5896 Inst = TmpInst;
5897 return true;
5898 }
5899
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005900 // Handle NEON VLD complex aliases.
Jim Grosbach8b31f952012-01-23 19:39:08 +00005901 case ARM::VLD1LNdWB_register_Asm_8:
5902 case ARM::VLD1LNdWB_register_Asm_16:
5903 case ARM::VLD1LNdWB_register_Asm_32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005904 MCInst TmpInst;
5905 // Shuffle the operands around so the lane index operand is in the
5906 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005907 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005908 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005909 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5910 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5911 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5912 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5913 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5914 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5915 TmpInst.addOperand(Inst.getOperand(1)); // lane
5916 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5917 TmpInst.addOperand(Inst.getOperand(6));
5918 Inst = TmpInst;
5919 return true;
5920 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005921
Jim Grosbach8b31f952012-01-23 19:39:08 +00005922 case ARM::VLD2LNdWB_register_Asm_8:
5923 case ARM::VLD2LNdWB_register_Asm_16:
5924 case ARM::VLD2LNdWB_register_Asm_32:
5925 case ARM::VLD2LNqWB_register_Asm_16:
5926 case ARM::VLD2LNqWB_register_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005927 MCInst TmpInst;
5928 // Shuffle the operands around so the lane index operand is in the
5929 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005930 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005931 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005932 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005933 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5934 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005935 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5936 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5937 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5938 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5939 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005940 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5941 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005942 TmpInst.addOperand(Inst.getOperand(1)); // lane
5943 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5944 TmpInst.addOperand(Inst.getOperand(6));
5945 Inst = TmpInst;
5946 return true;
5947 }
5948
Jim Grosbach3a678af2012-01-23 21:53:26 +00005949 case ARM::VLD3LNdWB_register_Asm_8:
5950 case ARM::VLD3LNdWB_register_Asm_16:
5951 case ARM::VLD3LNdWB_register_Asm_32:
5952 case ARM::VLD3LNqWB_register_Asm_16:
5953 case ARM::VLD3LNqWB_register_Asm_32: {
5954 MCInst TmpInst;
5955 // Shuffle the operands around so the lane index operand is in the
5956 // right place.
5957 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005958 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005959 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5960 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5961 Spacing));
5962 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005963 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005964 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5965 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5966 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5967 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5968 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5969 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5970 Spacing));
5971 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005972 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005973 TmpInst.addOperand(Inst.getOperand(1)); // lane
5974 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5975 TmpInst.addOperand(Inst.getOperand(6));
5976 Inst = TmpInst;
5977 return true;
5978 }
5979
Jim Grosbache983a132012-01-24 18:37:25 +00005980 case ARM::VLD4LNdWB_register_Asm_8:
5981 case ARM::VLD4LNdWB_register_Asm_16:
5982 case ARM::VLD4LNdWB_register_Asm_32:
5983 case ARM::VLD4LNqWB_register_Asm_16:
5984 case ARM::VLD4LNqWB_register_Asm_32: {
5985 MCInst TmpInst;
5986 // Shuffle the operands around so the lane index operand is in the
5987 // right place.
5988 unsigned Spacing;
5989 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
5990 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5991 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5992 Spacing));
5993 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5994 Spacing * 2));
5995 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5996 Spacing * 3));
5997 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5998 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5999 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6000 TmpInst.addOperand(Inst.getOperand(4)); // Rm
6001 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6002 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6003 Spacing));
6004 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6005 Spacing * 2));
6006 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6007 Spacing * 3));
6008 TmpInst.addOperand(Inst.getOperand(1)); // lane
6009 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
6010 TmpInst.addOperand(Inst.getOperand(6));
6011 Inst = TmpInst;
6012 return true;
6013 }
6014
Jim Grosbach8b31f952012-01-23 19:39:08 +00006015 case ARM::VLD1LNdWB_fixed_Asm_8:
6016 case ARM::VLD1LNdWB_fixed_Asm_16:
6017 case ARM::VLD1LNdWB_fixed_Asm_32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00006018 MCInst TmpInst;
6019 // Shuffle the operands around so the lane index operand is in the
6020 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006021 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006022 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00006023 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6024 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6025 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6026 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6027 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6028 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6029 TmpInst.addOperand(Inst.getOperand(1)); // lane
6030 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6031 TmpInst.addOperand(Inst.getOperand(5));
6032 Inst = TmpInst;
6033 return true;
6034 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006035
Jim Grosbach8b31f952012-01-23 19:39:08 +00006036 case ARM::VLD2LNdWB_fixed_Asm_8:
6037 case ARM::VLD2LNdWB_fixed_Asm_16:
6038 case ARM::VLD2LNdWB_fixed_Asm_32:
6039 case ARM::VLD2LNqWB_fixed_Asm_16:
6040 case ARM::VLD2LNqWB_fixed_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006041 MCInst TmpInst;
6042 // Shuffle the operands around so the lane index operand is in the
6043 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006044 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006045 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006046 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006047 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6048 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006049 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6050 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6051 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6052 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6053 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006054 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6055 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006056 TmpInst.addOperand(Inst.getOperand(1)); // lane
6057 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6058 TmpInst.addOperand(Inst.getOperand(5));
6059 Inst = TmpInst;
6060 return true;
6061 }
6062
Jim Grosbach3a678af2012-01-23 21:53:26 +00006063 case ARM::VLD3LNdWB_fixed_Asm_8:
6064 case ARM::VLD3LNdWB_fixed_Asm_16:
6065 case ARM::VLD3LNdWB_fixed_Asm_32:
6066 case ARM::VLD3LNqWB_fixed_Asm_16:
6067 case ARM::VLD3LNqWB_fixed_Asm_32: {
6068 MCInst TmpInst;
6069 // Shuffle the operands around so the lane index operand is in the
6070 // right place.
6071 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006072 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006073 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6074 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6075 Spacing));
6076 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006077 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006078 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6079 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6080 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6081 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6082 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6083 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6084 Spacing));
6085 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006086 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006087 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 Grosbache983a132012-01-24 18:37:25 +00006094 case ARM::VLD4LNdWB_fixed_Asm_8:
6095 case ARM::VLD4LNdWB_fixed_Asm_16:
6096 case ARM::VLD4LNdWB_fixed_Asm_32:
6097 case ARM::VLD4LNqWB_fixed_Asm_16:
6098 case ARM::VLD4LNqWB_fixed_Asm_32: {
6099 MCInst TmpInst;
6100 // Shuffle the operands around so the lane index operand is in the
6101 // right place.
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(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6110 Spacing * 3));
6111 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6112 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6113 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6114 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6115 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6116 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6117 Spacing));
6118 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6119 Spacing * 2));
6120 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6121 Spacing * 3));
6122 TmpInst.addOperand(Inst.getOperand(1)); // lane
6123 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6124 TmpInst.addOperand(Inst.getOperand(5));
6125 Inst = TmpInst;
6126 return true;
6127 }
6128
Jim Grosbach8b31f952012-01-23 19:39:08 +00006129 case ARM::VLD1LNdAsm_8:
6130 case ARM::VLD1LNdAsm_16:
6131 case ARM::VLD1LNdAsm_32: {
Jim Grosbach7636bf62011-12-02 00:35:16 +00006132 MCInst TmpInst;
6133 // Shuffle the operands around so the lane index operand is in the
6134 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006135 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006136 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach7636bf62011-12-02 00:35:16 +00006137 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6138 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6139 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6140 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6141 TmpInst.addOperand(Inst.getOperand(1)); // lane
6142 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6143 TmpInst.addOperand(Inst.getOperand(5));
6144 Inst = TmpInst;
6145 return true;
6146 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006147
Jim Grosbach8b31f952012-01-23 19:39:08 +00006148 case ARM::VLD2LNdAsm_8:
6149 case ARM::VLD2LNdAsm_16:
6150 case ARM::VLD2LNdAsm_32:
6151 case ARM::VLD2LNqAsm_16:
6152 case ARM::VLD2LNqAsm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006153 MCInst TmpInst;
6154 // Shuffle the operands around so the lane index operand is in the
6155 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006156 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006157 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006158 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006159 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6160 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006161 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6162 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6163 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006164 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6165 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006166 TmpInst.addOperand(Inst.getOperand(1)); // lane
6167 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6168 TmpInst.addOperand(Inst.getOperand(5));
6169 Inst = TmpInst;
6170 return true;
6171 }
Jim Grosbach3a678af2012-01-23 21:53:26 +00006172
6173 case ARM::VLD3LNdAsm_8:
6174 case ARM::VLD3LNdAsm_16:
6175 case ARM::VLD3LNdAsm_32:
6176 case ARM::VLD3LNqAsm_16:
6177 case ARM::VLD3LNqAsm_32: {
6178 MCInst TmpInst;
6179 // Shuffle the operands around so the lane index operand is in the
6180 // right place.
6181 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006182 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006183 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6184 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6185 Spacing));
6186 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006187 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006188 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6189 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6190 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6191 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6192 Spacing));
6193 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006194 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006195 TmpInst.addOperand(Inst.getOperand(1)); // lane
6196 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6197 TmpInst.addOperand(Inst.getOperand(5));
6198 Inst = TmpInst;
6199 return true;
6200 }
6201
Jim Grosbache983a132012-01-24 18:37:25 +00006202 case ARM::VLD4LNdAsm_8:
6203 case ARM::VLD4LNdAsm_16:
6204 case ARM::VLD4LNdAsm_32:
6205 case ARM::VLD4LNqAsm_16:
6206 case ARM::VLD4LNqAsm_32: {
6207 MCInst TmpInst;
6208 // Shuffle the operands around so the lane index operand is in the
6209 // right place.
6210 unsigned Spacing;
6211 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6212 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6213 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6214 Spacing));
6215 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6216 Spacing * 2));
6217 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6218 Spacing * 3));
6219 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6220 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6221 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== 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(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6227 Spacing * 3));
6228 TmpInst.addOperand(Inst.getOperand(1)); // lane
6229 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6230 TmpInst.addOperand(Inst.getOperand(5));
6231 Inst = TmpInst;
6232 return true;
6233 }
6234
Jim Grosbach5e59f7e2012-01-24 23:47:04 +00006235 // VLD3DUP single 3-element structure to all lanes instructions.
6236 case ARM::VLD3DUPdAsm_8:
6237 case ARM::VLD3DUPdAsm_16:
6238 case ARM::VLD3DUPdAsm_32:
6239 case ARM::VLD3DUPqAsm_8:
6240 case ARM::VLD3DUPqAsm_16:
6241 case ARM::VLD3DUPqAsm_32: {
6242 MCInst TmpInst;
6243 unsigned Spacing;
6244 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6245 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6246 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6247 Spacing));
6248 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6249 Spacing * 2));
6250 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6251 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6252 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6253 TmpInst.addOperand(Inst.getOperand(4));
6254 Inst = TmpInst;
6255 return true;
6256 }
6257
6258 case ARM::VLD3DUPdWB_fixed_Asm_8:
6259 case ARM::VLD3DUPdWB_fixed_Asm_16:
6260 case ARM::VLD3DUPdWB_fixed_Asm_32:
6261 case ARM::VLD3DUPqWB_fixed_Asm_8:
6262 case ARM::VLD3DUPqWB_fixed_Asm_16:
6263 case ARM::VLD3DUPqWB_fixed_Asm_32: {
6264 MCInst TmpInst;
6265 unsigned Spacing;
6266 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6267 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6268 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6269 Spacing));
6270 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6271 Spacing * 2));
6272 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6273 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6274 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6275 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6276 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6277 TmpInst.addOperand(Inst.getOperand(4));
6278 Inst = TmpInst;
6279 return true;
6280 }
6281
6282 case ARM::VLD3DUPdWB_register_Asm_8:
6283 case ARM::VLD3DUPdWB_register_Asm_16:
6284 case ARM::VLD3DUPdWB_register_Asm_32:
6285 case ARM::VLD3DUPqWB_register_Asm_8:
6286 case ARM::VLD3DUPqWB_register_Asm_16:
6287 case ARM::VLD3DUPqWB_register_Asm_32: {
6288 MCInst TmpInst;
6289 unsigned Spacing;
6290 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6291 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6292 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6293 Spacing));
6294 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6295 Spacing * 2));
6296 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6297 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6298 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6299 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6300 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6301 TmpInst.addOperand(Inst.getOperand(5));
6302 Inst = TmpInst;
6303 return true;
6304 }
6305
Jim Grosbachc387fc62012-01-23 23:20:46 +00006306 // VLD3 multiple 3-element structure instructions.
6307 case ARM::VLD3dAsm_8:
6308 case ARM::VLD3dAsm_16:
6309 case ARM::VLD3dAsm_32:
6310 case ARM::VLD3qAsm_8:
6311 case ARM::VLD3qAsm_16:
6312 case ARM::VLD3qAsm_32: {
6313 MCInst TmpInst;
6314 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006315 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00006316 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6317 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6318 Spacing));
6319 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6320 Spacing * 2));
6321 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6322 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6323 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6324 TmpInst.addOperand(Inst.getOperand(4));
6325 Inst = TmpInst;
6326 return true;
6327 }
6328
6329 case ARM::VLD3dWB_fixed_Asm_8:
6330 case ARM::VLD3dWB_fixed_Asm_16:
6331 case ARM::VLD3dWB_fixed_Asm_32:
6332 case ARM::VLD3qWB_fixed_Asm_8:
6333 case ARM::VLD3qWB_fixed_Asm_16:
6334 case ARM::VLD3qWB_fixed_Asm_32: {
6335 MCInst TmpInst;
6336 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006337 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00006338 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6339 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6340 Spacing));
6341 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6342 Spacing * 2));
6343 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6344 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6345 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6346 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6347 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6348 TmpInst.addOperand(Inst.getOperand(4));
6349 Inst = TmpInst;
6350 return true;
6351 }
6352
6353 case ARM::VLD3dWB_register_Asm_8:
6354 case ARM::VLD3dWB_register_Asm_16:
6355 case ARM::VLD3dWB_register_Asm_32:
6356 case ARM::VLD3qWB_register_Asm_8:
6357 case ARM::VLD3qWB_register_Asm_16:
6358 case ARM::VLD3qWB_register_Asm_32: {
6359 MCInst TmpInst;
6360 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006361 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00006362 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6363 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6364 Spacing));
6365 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6366 Spacing * 2));
6367 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6368 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6369 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6370 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6371 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6372 TmpInst.addOperand(Inst.getOperand(5));
6373 Inst = TmpInst;
6374 return true;
6375 }
6376
Jim Grosbacha57a36a2012-01-25 00:01:08 +00006377 // VLD4DUP single 3-element structure to all lanes instructions.
6378 case ARM::VLD4DUPdAsm_8:
6379 case ARM::VLD4DUPdAsm_16:
6380 case ARM::VLD4DUPdAsm_32:
6381 case ARM::VLD4DUPqAsm_8:
6382 case ARM::VLD4DUPqAsm_16:
6383 case ARM::VLD4DUPqAsm_32: {
6384 MCInst TmpInst;
6385 unsigned Spacing;
6386 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6387 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6388 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6389 Spacing));
6390 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6391 Spacing * 2));
6392 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6393 Spacing * 3));
6394 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6395 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6396 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6397 TmpInst.addOperand(Inst.getOperand(4));
6398 Inst = TmpInst;
6399 return true;
6400 }
6401
6402 case ARM::VLD4DUPdWB_fixed_Asm_8:
6403 case ARM::VLD4DUPdWB_fixed_Asm_16:
6404 case ARM::VLD4DUPdWB_fixed_Asm_32:
6405 case ARM::VLD4DUPqWB_fixed_Asm_8:
6406 case ARM::VLD4DUPqWB_fixed_Asm_16:
6407 case ARM::VLD4DUPqWB_fixed_Asm_32: {
6408 MCInst TmpInst;
6409 unsigned Spacing;
6410 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6411 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6412 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6413 Spacing));
6414 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6415 Spacing * 2));
6416 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6417 Spacing * 3));
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(3)); // CondCode
6423 TmpInst.addOperand(Inst.getOperand(4));
6424 Inst = TmpInst;
6425 return true;
6426 }
6427
6428 case ARM::VLD4DUPdWB_register_Asm_8:
6429 case ARM::VLD4DUPdWB_register_Asm_16:
6430 case ARM::VLD4DUPdWB_register_Asm_32:
6431 case ARM::VLD4DUPqWB_register_Asm_8:
6432 case ARM::VLD4DUPqWB_register_Asm_16:
6433 case ARM::VLD4DUPqWB_register_Asm_32: {
6434 MCInst TmpInst;
6435 unsigned Spacing;
6436 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6437 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6438 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6439 Spacing));
6440 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6441 Spacing * 2));
6442 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6443 Spacing * 3));
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(4)); // CondCode
6449 TmpInst.addOperand(Inst.getOperand(5));
6450 Inst = TmpInst;
6451 return true;
6452 }
6453
6454 // VLD4 multiple 4-element structure instructions.
Jim Grosbach8abe7e32012-01-24 00:43:17 +00006455 case ARM::VLD4dAsm_8:
6456 case ARM::VLD4dAsm_16:
6457 case ARM::VLD4dAsm_32:
6458 case ARM::VLD4qAsm_8:
6459 case ARM::VLD4qAsm_16:
6460 case ARM::VLD4qAsm_32: {
6461 MCInst TmpInst;
6462 unsigned Spacing;
6463 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6464 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6465 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6466 Spacing));
6467 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6468 Spacing * 2));
6469 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6470 Spacing * 3));
6471 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6472 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6473 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6474 TmpInst.addOperand(Inst.getOperand(4));
6475 Inst = TmpInst;
6476 return true;
6477 }
6478
6479 case ARM::VLD4dWB_fixed_Asm_8:
6480 case ARM::VLD4dWB_fixed_Asm_16:
6481 case ARM::VLD4dWB_fixed_Asm_32:
6482 case ARM::VLD4qWB_fixed_Asm_8:
6483 case ARM::VLD4qWB_fixed_Asm_16:
6484 case ARM::VLD4qWB_fixed_Asm_32: {
6485 MCInst TmpInst;
6486 unsigned Spacing;
6487 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6488 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6489 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6490 Spacing));
6491 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6492 Spacing * 2));
6493 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6494 Spacing * 3));
6495 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6496 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6497 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6498 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6499 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6500 TmpInst.addOperand(Inst.getOperand(4));
6501 Inst = TmpInst;
6502 return true;
6503 }
6504
6505 case ARM::VLD4dWB_register_Asm_8:
6506 case ARM::VLD4dWB_register_Asm_16:
6507 case ARM::VLD4dWB_register_Asm_32:
6508 case ARM::VLD4qWB_register_Asm_8:
6509 case ARM::VLD4qWB_register_Asm_16:
6510 case ARM::VLD4qWB_register_Asm_32: {
6511 MCInst TmpInst;
6512 unsigned Spacing;
6513 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6514 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6515 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6516 Spacing));
6517 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6518 Spacing * 2));
6519 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6520 Spacing * 3));
6521 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6522 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6523 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6524 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6525 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6526 TmpInst.addOperand(Inst.getOperand(5));
6527 Inst = TmpInst;
6528 return true;
6529 }
6530
Jim Grosbachd7433e22012-01-23 23:45:44 +00006531 // VST3 multiple 3-element structure instructions.
6532 case ARM::VST3dAsm_8:
6533 case ARM::VST3dAsm_16:
6534 case ARM::VST3dAsm_32:
6535 case ARM::VST3qAsm_8:
6536 case ARM::VST3qAsm_16:
6537 case ARM::VST3qAsm_32: {
6538 MCInst TmpInst;
6539 unsigned Spacing;
6540 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6541 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6542 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6543 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6544 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6545 Spacing));
6546 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6547 Spacing * 2));
6548 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6549 TmpInst.addOperand(Inst.getOperand(4));
6550 Inst = TmpInst;
6551 return true;
6552 }
6553
6554 case ARM::VST3dWB_fixed_Asm_8:
6555 case ARM::VST3dWB_fixed_Asm_16:
6556 case ARM::VST3dWB_fixed_Asm_32:
6557 case ARM::VST3qWB_fixed_Asm_8:
6558 case ARM::VST3qWB_fixed_Asm_16:
6559 case ARM::VST3qWB_fixed_Asm_32: {
6560 MCInst TmpInst;
6561 unsigned Spacing;
6562 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6563 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6564 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6565 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6566 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6567 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6568 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6569 Spacing));
6570 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6571 Spacing * 2));
6572 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6573 TmpInst.addOperand(Inst.getOperand(4));
6574 Inst = TmpInst;
6575 return true;
6576 }
6577
6578 case ARM::VST3dWB_register_Asm_8:
6579 case ARM::VST3dWB_register_Asm_16:
6580 case ARM::VST3dWB_register_Asm_32:
6581 case ARM::VST3qWB_register_Asm_8:
6582 case ARM::VST3qWB_register_Asm_16:
6583 case ARM::VST3qWB_register_Asm_32: {
6584 MCInst TmpInst;
6585 unsigned Spacing;
6586 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6587 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6588 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6589 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6590 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6591 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6592 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6593 Spacing));
6594 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6595 Spacing * 2));
6596 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6597 TmpInst.addOperand(Inst.getOperand(5));
6598 Inst = TmpInst;
6599 return true;
6600 }
6601
Jim Grosbach539aab72012-01-24 00:58:13 +00006602 // VST4 multiple 3-element structure instructions.
6603 case ARM::VST4dAsm_8:
6604 case ARM::VST4dAsm_16:
6605 case ARM::VST4dAsm_32:
6606 case ARM::VST4qAsm_8:
6607 case ARM::VST4qAsm_16:
6608 case ARM::VST4qAsm_32: {
6609 MCInst TmpInst;
6610 unsigned Spacing;
6611 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6612 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6613 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6614 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6615 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6616 Spacing));
6617 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6618 Spacing * 2));
6619 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6620 Spacing * 3));
6621 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6622 TmpInst.addOperand(Inst.getOperand(4));
6623 Inst = TmpInst;
6624 return true;
6625 }
6626
6627 case ARM::VST4dWB_fixed_Asm_8:
6628 case ARM::VST4dWB_fixed_Asm_16:
6629 case ARM::VST4dWB_fixed_Asm_32:
6630 case ARM::VST4qWB_fixed_Asm_8:
6631 case ARM::VST4qWB_fixed_Asm_16:
6632 case ARM::VST4qWB_fixed_Asm_32: {
6633 MCInst TmpInst;
6634 unsigned Spacing;
6635 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6636 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6637 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6638 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6639 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6640 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6641 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6642 Spacing));
6643 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6644 Spacing * 2));
6645 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6646 Spacing * 3));
6647 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6648 TmpInst.addOperand(Inst.getOperand(4));
6649 Inst = TmpInst;
6650 return true;
6651 }
6652
6653 case ARM::VST4dWB_register_Asm_8:
6654 case ARM::VST4dWB_register_Asm_16:
6655 case ARM::VST4dWB_register_Asm_32:
6656 case ARM::VST4qWB_register_Asm_8:
6657 case ARM::VST4qWB_register_Asm_16:
6658 case ARM::VST4qWB_register_Asm_32: {
6659 MCInst TmpInst;
6660 unsigned Spacing;
6661 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6662 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6663 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6664 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6665 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6666 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6667 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6668 Spacing));
6669 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6670 Spacing * 2));
6671 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6672 Spacing * 3));
6673 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6674 TmpInst.addOperand(Inst.getOperand(5));
6675 Inst = TmpInst;
6676 return true;
6677 }
6678
Jim Grosbacha5378eb2012-04-11 00:15:16 +00006679 // Handle encoding choice for the shift-immediate instructions.
6680 case ARM::t2LSLri:
6681 case ARM::t2LSRri:
6682 case ARM::t2ASRri: {
6683 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6684 Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
6685 Inst.getOperand(5).getReg() == (inITBlock() ? 0 : ARM::CPSR) &&
6686 !(static_cast<ARMOperand*>(Operands[3])->isToken() &&
6687 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w")) {
6688 unsigned NewOpc;
6689 switch (Inst.getOpcode()) {
6690 default: llvm_unreachable("unexpected opcode");
6691 case ARM::t2LSLri: NewOpc = ARM::tLSLri; break;
6692 case ARM::t2LSRri: NewOpc = ARM::tLSRri; break;
6693 case ARM::t2ASRri: NewOpc = ARM::tASRri; break;
6694 }
6695 // The Thumb1 operands aren't in the same order. Awesome, eh?
6696 MCInst TmpInst;
6697 TmpInst.setOpcode(NewOpc);
6698 TmpInst.addOperand(Inst.getOperand(0));
6699 TmpInst.addOperand(Inst.getOperand(5));
6700 TmpInst.addOperand(Inst.getOperand(1));
6701 TmpInst.addOperand(Inst.getOperand(2));
6702 TmpInst.addOperand(Inst.getOperand(3));
6703 TmpInst.addOperand(Inst.getOperand(4));
6704 Inst = TmpInst;
6705 return true;
6706 }
6707 return false;
6708 }
6709
Jim Grosbach863d2af2011-12-13 22:45:11 +00006710 // Handle the Thumb2 mode MOV complex aliases.
Jim Grosbach2cc5cda2011-12-21 20:54:00 +00006711 case ARM::t2MOVsr:
6712 case ARM::t2MOVSsr: {
6713 // Which instruction to expand to depends on the CCOut operand and
6714 // whether we're in an IT block if the register operands are low
6715 // registers.
6716 bool isNarrow = false;
6717 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6718 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6719 isARMLowRegister(Inst.getOperand(2).getReg()) &&
6720 Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
6721 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsr))
6722 isNarrow = true;
6723 MCInst TmpInst;
6724 unsigned newOpc;
6725 switch(ARM_AM::getSORegShOp(Inst.getOperand(3).getImm())) {
6726 default: llvm_unreachable("unexpected opcode!");
6727 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRrr : ARM::t2ASRrr; break;
6728 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRrr : ARM::t2LSRrr; break;
6729 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLrr : ARM::t2LSLrr; break;
6730 case ARM_AM::ror: newOpc = isNarrow ? ARM::tROR : ARM::t2RORrr; break;
6731 }
6732 TmpInst.setOpcode(newOpc);
6733 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6734 if (isNarrow)
6735 TmpInst.addOperand(MCOperand::CreateReg(
6736 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6737 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6738 TmpInst.addOperand(Inst.getOperand(2)); // Rm
6739 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6740 TmpInst.addOperand(Inst.getOperand(5));
6741 if (!isNarrow)
6742 TmpInst.addOperand(MCOperand::CreateReg(
6743 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6744 Inst = TmpInst;
6745 return true;
6746 }
Jim Grosbach863d2af2011-12-13 22:45:11 +00006747 case ARM::t2MOVsi:
6748 case ARM::t2MOVSsi: {
6749 // Which instruction to expand to depends on the CCOut operand and
6750 // whether we're in an IT block if the register operands are low
6751 // registers.
6752 bool isNarrow = false;
6753 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6754 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6755 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
6756 isNarrow = true;
6757 MCInst TmpInst;
6758 unsigned newOpc;
6759 switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
6760 default: llvm_unreachable("unexpected opcode!");
6761 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
6762 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
6763 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
6764 case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
Jim Grosbach520dc782011-12-21 21:04:19 +00006765 case ARM_AM::rrx: isNarrow = false; newOpc = ARM::t2RRX; break;
Jim Grosbach863d2af2011-12-13 22:45:11 +00006766 }
6767 unsigned Ammount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
6768 if (Ammount == 32) Ammount = 0;
6769 TmpInst.setOpcode(newOpc);
6770 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6771 if (isNarrow)
6772 TmpInst.addOperand(MCOperand::CreateReg(
6773 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6774 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbach520dc782011-12-21 21:04:19 +00006775 if (newOpc != ARM::t2RRX)
6776 TmpInst.addOperand(MCOperand::CreateImm(Ammount));
Jim Grosbach863d2af2011-12-13 22:45:11 +00006777 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6778 TmpInst.addOperand(Inst.getOperand(4));
6779 if (!isNarrow)
6780 TmpInst.addOperand(MCOperand::CreateReg(
6781 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6782 Inst = TmpInst;
6783 return true;
6784 }
6785 // Handle the ARM mode MOV complex aliases.
Jim Grosbach23f22072011-11-16 18:31:45 +00006786 case ARM::ASRr:
6787 case ARM::LSRr:
6788 case ARM::LSLr:
6789 case ARM::RORr: {
6790 ARM_AM::ShiftOpc ShiftTy;
6791 switch(Inst.getOpcode()) {
6792 default: llvm_unreachable("unexpected opcode!");
6793 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
6794 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
6795 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
6796 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
6797 }
Jim Grosbach23f22072011-11-16 18:31:45 +00006798 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
6799 MCInst TmpInst;
6800 TmpInst.setOpcode(ARM::MOVsr);
6801 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6802 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6803 TmpInst.addOperand(Inst.getOperand(2)); // Rm
6804 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6805 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6806 TmpInst.addOperand(Inst.getOperand(4));
6807 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6808 Inst = TmpInst;
6809 return true;
6810 }
Jim Grosbachee10ff82011-11-10 19:18:01 +00006811 case ARM::ASRi:
6812 case ARM::LSRi:
6813 case ARM::LSLi:
6814 case ARM::RORi: {
6815 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachee10ff82011-11-10 19:18:01 +00006816 switch(Inst.getOpcode()) {
6817 default: llvm_unreachable("unexpected opcode!");
6818 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
6819 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
6820 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
6821 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
6822 }
6823 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach48b368b2011-11-16 19:05:59 +00006824 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachee10ff82011-11-10 19:18:01 +00006825 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
Richard Bartonb56e4112012-04-25 18:00:18 +00006826 // A shift by 32 should be encoded as 0 when permitted
6827 if (Amt == 32 && (ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr))
6828 Amt = 0;
Jim Grosbachee10ff82011-11-10 19:18:01 +00006829 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach71810ab2011-11-10 16:44:55 +00006830 MCInst TmpInst;
Jim Grosbachee10ff82011-11-10 19:18:01 +00006831 TmpInst.setOpcode(Opc);
Jim Grosbach71810ab2011-11-10 16:44:55 +00006832 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6833 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachee10ff82011-11-10 19:18:01 +00006834 if (Opc == ARM::MOVsi)
6835 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach71810ab2011-11-10 16:44:55 +00006836 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6837 TmpInst.addOperand(Inst.getOperand(4));
6838 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6839 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006840 return true;
Jim Grosbach71810ab2011-11-10 16:44:55 +00006841 }
Jim Grosbach48b368b2011-11-16 19:05:59 +00006842 case ARM::RRXi: {
6843 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
6844 MCInst TmpInst;
6845 TmpInst.setOpcode(ARM::MOVsi);
6846 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6847 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6848 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6849 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6850 TmpInst.addOperand(Inst.getOperand(3));
6851 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
6852 Inst = TmpInst;
6853 return true;
6854 }
Jim Grosbach0352b462011-11-10 23:58:34 +00006855 case ARM::t2LDMIA_UPD: {
6856 // If this is a load of a single register, then we should use
6857 // a post-indexed LDR instruction instead, per the ARM ARM.
6858 if (Inst.getNumOperands() != 5)
6859 return false;
6860 MCInst TmpInst;
6861 TmpInst.setOpcode(ARM::t2LDR_POST);
6862 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6863 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6864 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6865 TmpInst.addOperand(MCOperand::CreateImm(4));
6866 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6867 TmpInst.addOperand(Inst.getOperand(3));
6868 Inst = TmpInst;
6869 return true;
6870 }
6871 case ARM::t2STMDB_UPD: {
6872 // If this is a store of a single register, then we should use
6873 // a pre-indexed STR instruction instead, per the ARM ARM.
6874 if (Inst.getNumOperands() != 5)
6875 return false;
6876 MCInst TmpInst;
6877 TmpInst.setOpcode(ARM::t2STR_PRE);
6878 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6879 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6880 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6881 TmpInst.addOperand(MCOperand::CreateImm(-4));
6882 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6883 TmpInst.addOperand(Inst.getOperand(3));
6884 Inst = TmpInst;
6885 return true;
6886 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00006887 case ARM::LDMIA_UPD:
6888 // If this is a load of a single register via a 'pop', then we should use
6889 // a post-indexed LDR instruction instead, per the ARM ARM.
6890 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
6891 Inst.getNumOperands() == 5) {
6892 MCInst TmpInst;
6893 TmpInst.setOpcode(ARM::LDR_POST_IMM);
6894 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6895 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6896 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6897 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
6898 TmpInst.addOperand(MCOperand::CreateImm(4));
6899 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6900 TmpInst.addOperand(Inst.getOperand(3));
6901 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006902 return true;
Jim Grosbachf8fce712011-08-11 17:35:48 +00006903 }
6904 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00006905 case ARM::STMDB_UPD:
6906 // If this is a store of a single register via a 'push', then we should use
6907 // a pre-indexed STR instruction instead, per the ARM ARM.
6908 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
6909 Inst.getNumOperands() == 5) {
6910 MCInst TmpInst;
6911 TmpInst.setOpcode(ARM::STR_PRE_IMM);
6912 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6913 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6914 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
6915 TmpInst.addOperand(MCOperand::CreateImm(-4));
6916 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6917 TmpInst.addOperand(Inst.getOperand(3));
6918 Inst = TmpInst;
6919 }
6920 break;
Jim Grosbachda847862011-12-05 21:06:26 +00006921 case ARM::t2ADDri12:
6922 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
6923 // mnemonic was used (not "addw"), encoding T3 is preferred.
6924 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
6925 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
6926 break;
6927 Inst.setOpcode(ARM::t2ADDri);
6928 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
6929 break;
6930 case ARM::t2SUBri12:
6931 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
6932 // mnemonic was used (not "subw"), encoding T3 is preferred.
6933 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
6934 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
6935 break;
6936 Inst.setOpcode(ARM::t2SUBri);
6937 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
6938 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006939 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00006940 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6941 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6942 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6943 // to encoding T1 if <Rd> is omitted."
Jim Grosbachc0164f82012-03-30 16:31:31 +00006944 if ((unsigned)Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006945 Inst.setOpcode(ARM::tADDi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006946 return true;
6947 }
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006948 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00006949 case ARM::tSUBi8:
6950 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6951 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6952 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6953 // to encoding T1 if <Rd> is omitted."
Jim Grosbachc0164f82012-03-30 16:31:31 +00006954 if ((unsigned)Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachf67e8552011-09-16 22:58:42 +00006955 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006956 return true;
6957 }
Jim Grosbachf67e8552011-09-16 22:58:42 +00006958 break;
Jim Grosbach2d30d942012-03-30 17:20:40 +00006959 case ARM::t2ADDri:
6960 case ARM::t2SUBri: {
6961 // If the destination and first source operand are the same, and
6962 // the flags are compatible with the current IT status, use encoding T2
6963 // instead of T3. For compatibility with the system 'as'. Make sure the
6964 // wide encoding wasn't explicit.
6965 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
Jim Grosbach8f1148b2012-03-30 18:39:43 +00006966 !isARMLowRegister(Inst.getOperand(0).getReg()) ||
Jim Grosbach2d30d942012-03-30 17:20:40 +00006967 (unsigned)Inst.getOperand(2).getImm() > 255 ||
6968 ((!inITBlock() && Inst.getOperand(5).getReg() != ARM::CPSR) ||
6969 (inITBlock() && Inst.getOperand(5).getReg() != 0)) ||
6970 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6971 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
6972 break;
6973 MCInst TmpInst;
6974 TmpInst.setOpcode(Inst.getOpcode() == ARM::t2ADDri ?
6975 ARM::tADDi8 : ARM::tSUBi8);
6976 TmpInst.addOperand(Inst.getOperand(0));
6977 TmpInst.addOperand(Inst.getOperand(5));
6978 TmpInst.addOperand(Inst.getOperand(0));
6979 TmpInst.addOperand(Inst.getOperand(2));
6980 TmpInst.addOperand(Inst.getOperand(3));
6981 TmpInst.addOperand(Inst.getOperand(4));
6982 Inst = TmpInst;
6983 return true;
6984 }
Jim Grosbach927b9df2011-12-05 22:16:39 +00006985 case ARM::t2ADDrr: {
6986 // If the destination and first source operand are the same, and
6987 // there's no setting of the flags, use encoding T2 instead of T3.
6988 // Note that this is only for ADD, not SUB. This mirrors the system
6989 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
6990 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
6991 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbach713c7022011-12-05 22:27:04 +00006992 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6993 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbach927b9df2011-12-05 22:16:39 +00006994 break;
6995 MCInst TmpInst;
6996 TmpInst.setOpcode(ARM::tADDhirr);
6997 TmpInst.addOperand(Inst.getOperand(0));
6998 TmpInst.addOperand(Inst.getOperand(0));
6999 TmpInst.addOperand(Inst.getOperand(2));
7000 TmpInst.addOperand(Inst.getOperand(3));
7001 TmpInst.addOperand(Inst.getOperand(4));
7002 Inst = TmpInst;
7003 return true;
7004 }
Jim Grosbacha9cc08f2012-04-27 23:51:36 +00007005 case ARM::tADDrSP: {
7006 // If the non-SP source operand and the destination operand are not the
7007 // same, we need to use the 32-bit encoding if it's available.
7008 if (Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg()) {
7009 Inst.setOpcode(ARM::t2ADDrr);
7010 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
7011 return true;
7012 }
7013 break;
7014 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00007015 case ARM::tB:
7016 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00007017 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson51f6a7a2011-09-09 21:48:23 +00007018 Inst.setOpcode(ARM::tBcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00007019 return true;
7020 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00007021 break;
7022 case ARM::t2B:
7023 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00007024 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson51f6a7a2011-09-09 21:48:23 +00007025 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00007026 return true;
7027 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00007028 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00007029 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00007030 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbach83ec8772011-11-10 23:42:14 +00007031 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbachc0755102011-08-31 21:17:31 +00007032 Inst.setOpcode(ARM::t2B);
Jim Grosbach83ec8772011-11-10 23:42:14 +00007033 return true;
7034 }
Jim Grosbachc0755102011-08-31 21:17:31 +00007035 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00007036 case ARM::tBcc:
7037 // If the conditional is AL, we really want tB.
Jim Grosbach83ec8772011-11-10 23:42:14 +00007038 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbach395b4532011-08-17 22:57:40 +00007039 Inst.setOpcode(ARM::tB);
Jim Grosbach83ec8772011-11-10 23:42:14 +00007040 return true;
7041 }
Jim Grosbach3ce23d32011-08-18 16:08:39 +00007042 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00007043 case ARM::tLDMIA: {
7044 // If the register list contains any high registers, or if the writeback
7045 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
7046 // instead if we're in Thumb2. Otherwise, this should have generated
7047 // an error in validateInstruction().
7048 unsigned Rn = Inst.getOperand(0).getReg();
7049 bool hasWritebackToken =
7050 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
7051 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
7052 bool listContainsBase;
7053 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
7054 (!listContainsBase && !hasWritebackToken) ||
7055 (listContainsBase && hasWritebackToken)) {
7056 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
7057 assert (isThumbTwo());
7058 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
7059 // If we're switching to the updating version, we need to insert
7060 // the writeback tied operand.
7061 if (hasWritebackToken)
7062 Inst.insert(Inst.begin(),
7063 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbach83ec8772011-11-10 23:42:14 +00007064 return true;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00007065 }
7066 break;
7067 }
Jim Grosbach8213c962011-09-16 20:50:13 +00007068 case ARM::tSTMIA_UPD: {
7069 // If the register list contains any high registers, we need to use
7070 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
7071 // should have generated an error in validateInstruction().
7072 unsigned Rn = Inst.getOperand(0).getReg();
7073 bool listContainsBase;
7074 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
7075 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
7076 assert (isThumbTwo());
7077 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbach83ec8772011-11-10 23:42:14 +00007078 return true;
Jim Grosbach8213c962011-09-16 20:50:13 +00007079 }
7080 break;
7081 }
Jim Grosbach54026372011-11-10 23:17:11 +00007082 case ARM::tPOP: {
7083 bool listContainsBase;
7084 // If the register list contains any high registers, we need to use
7085 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
7086 // should have generated an error in validateInstruction().
7087 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00007088 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00007089 assert (isThumbTwo());
7090 Inst.setOpcode(ARM::t2LDMIA_UPD);
7091 // Add the base register and writeback operands.
7092 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
7093 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00007094 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00007095 }
7096 case ARM::tPUSH: {
7097 bool listContainsBase;
7098 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00007099 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00007100 assert (isThumbTwo());
7101 Inst.setOpcode(ARM::t2STMDB_UPD);
7102 // Add the base register and writeback operands.
7103 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
7104 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00007105 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00007106 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00007107 case ARM::t2MOVi: {
7108 // If we can use the 16-bit encoding and the user didn't explicitly
7109 // request the 32-bit variant, transform it here.
7110 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
Jim Grosbachc0164f82012-03-30 16:31:31 +00007111 (unsigned)Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00007112 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
7113 Inst.getOperand(4).getReg() == ARM::CPSR) ||
7114 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00007115 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
7116 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
7117 // The operands aren't in the same order for tMOVi8...
7118 MCInst TmpInst;
7119 TmpInst.setOpcode(ARM::tMOVi8);
7120 TmpInst.addOperand(Inst.getOperand(0));
7121 TmpInst.addOperand(Inst.getOperand(4));
7122 TmpInst.addOperand(Inst.getOperand(1));
7123 TmpInst.addOperand(Inst.getOperand(2));
7124 TmpInst.addOperand(Inst.getOperand(3));
7125 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00007126 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00007127 }
7128 break;
7129 }
7130 case ARM::t2MOVr: {
7131 // If we can use the 16-bit encoding and the user didn't explicitly
7132 // request the 32-bit variant, transform it here.
7133 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
7134 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7135 Inst.getOperand(2).getImm() == ARMCC::AL &&
7136 Inst.getOperand(4).getReg() == ARM::CPSR &&
7137 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
7138 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
7139 // The operands aren't the same for tMOV[S]r... (no cc_out)
7140 MCInst TmpInst;
7141 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
7142 TmpInst.addOperand(Inst.getOperand(0));
7143 TmpInst.addOperand(Inst.getOperand(1));
7144 TmpInst.addOperand(Inst.getOperand(2));
7145 TmpInst.addOperand(Inst.getOperand(3));
7146 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00007147 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00007148 }
7149 break;
7150 }
Jim Grosbach326efe52011-09-19 20:29:33 +00007151 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00007152 case ARM::t2SXTB:
7153 case ARM::t2UXTH:
7154 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00007155 // If we can use the 16-bit encoding and the user didn't explicitly
7156 // request the 32-bit variant, transform it here.
7157 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
7158 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7159 Inst.getOperand(2).getImm() == 0 &&
7160 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
7161 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00007162 unsigned NewOpc;
7163 switch (Inst.getOpcode()) {
7164 default: llvm_unreachable("Illegal opcode!");
7165 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
7166 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
7167 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
7168 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
7169 }
Jim Grosbach326efe52011-09-19 20:29:33 +00007170 // The operands aren't the same for thumb1 (no rotate operand).
7171 MCInst TmpInst;
7172 TmpInst.setOpcode(NewOpc);
7173 TmpInst.addOperand(Inst.getOperand(0));
7174 TmpInst.addOperand(Inst.getOperand(1));
7175 TmpInst.addOperand(Inst.getOperand(3));
7176 TmpInst.addOperand(Inst.getOperand(4));
7177 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00007178 return true;
Jim Grosbach326efe52011-09-19 20:29:33 +00007179 }
7180 break;
7181 }
Jim Grosbach04b5d932011-12-20 00:59:38 +00007182 case ARM::MOVsi: {
7183 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm());
Richard Bartonb56e4112012-04-25 18:00:18 +00007184 // rrx shifts and asr/lsr of #32 is encoded as 0
7185 if (SOpc == ARM_AM::rrx || SOpc == ARM_AM::asr || SOpc == ARM_AM::lsr)
7186 return false;
Jim Grosbach04b5d932011-12-20 00:59:38 +00007187 if (ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()) == 0) {
7188 // Shifting by zero is accepted as a vanilla 'MOVr'
7189 MCInst TmpInst;
7190 TmpInst.setOpcode(ARM::MOVr);
7191 TmpInst.addOperand(Inst.getOperand(0));
7192 TmpInst.addOperand(Inst.getOperand(1));
7193 TmpInst.addOperand(Inst.getOperand(3));
7194 TmpInst.addOperand(Inst.getOperand(4));
7195 TmpInst.addOperand(Inst.getOperand(5));
7196 Inst = TmpInst;
7197 return true;
7198 }
7199 return false;
7200 }
Jim Grosbach8d9550b2011-12-22 18:04:04 +00007201 case ARM::ANDrsi:
7202 case ARM::ORRrsi:
7203 case ARM::EORrsi:
7204 case ARM::BICrsi:
7205 case ARM::SUBrsi:
7206 case ARM::ADDrsi: {
7207 unsigned newOpc;
7208 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(3).getImm());
7209 if (SOpc == ARM_AM::rrx) return false;
7210 switch (Inst.getOpcode()) {
Craig Topperbc219812012-02-07 02:50:20 +00007211 default: llvm_unreachable("unexpected opcode!");
Jim Grosbach8d9550b2011-12-22 18:04:04 +00007212 case ARM::ANDrsi: newOpc = ARM::ANDrr; break;
7213 case ARM::ORRrsi: newOpc = ARM::ORRrr; break;
7214 case ARM::EORrsi: newOpc = ARM::EORrr; break;
7215 case ARM::BICrsi: newOpc = ARM::BICrr; break;
7216 case ARM::SUBrsi: newOpc = ARM::SUBrr; break;
7217 case ARM::ADDrsi: newOpc = ARM::ADDrr; break;
7218 }
7219 // If the shift is by zero, use the non-shifted instruction definition.
7220 if (ARM_AM::getSORegOffset(Inst.getOperand(3).getImm()) == 0) {
7221 MCInst TmpInst;
7222 TmpInst.setOpcode(newOpc);
7223 TmpInst.addOperand(Inst.getOperand(0));
7224 TmpInst.addOperand(Inst.getOperand(1));
7225 TmpInst.addOperand(Inst.getOperand(2));
7226 TmpInst.addOperand(Inst.getOperand(4));
7227 TmpInst.addOperand(Inst.getOperand(5));
7228 TmpInst.addOperand(Inst.getOperand(6));
7229 Inst = TmpInst;
7230 return true;
7231 }
7232 return false;
7233 }
Jim Grosbach74423e32012-01-25 19:52:01 +00007234 case ARM::ITasm:
Jim Grosbach89df9962011-08-26 21:43:41 +00007235 case ARM::t2IT: {
7236 // The mask bits for all but the first condition are represented as
7237 // the low bit of the condition code value implies 't'. We currently
7238 // always have 1 implies 't', so XOR toggle the bits if the low bit
Richard Barton4d2f0772012-04-27 08:42:59 +00007239 // of the condition code is zero.
Jim Grosbach89df9962011-08-26 21:43:41 +00007240 MCOperand &MO = Inst.getOperand(1);
7241 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007242 unsigned OrigMask = Mask;
7243 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00007244 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00007245 assert(Mask && TZ <= 3 && "illegal IT mask value!");
7246 for (unsigned i = 3; i != TZ; --i)
7247 Mask ^= 1 << i;
Richard Barton4d2f0772012-04-27 08:42:59 +00007248 }
Jim Grosbach89df9962011-08-26 21:43:41 +00007249 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007250
7251 // Set up the IT block state according to the IT instruction we just
7252 // matched.
7253 assert(!inITBlock() && "nested IT blocks?!");
7254 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
7255 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
7256 ITState.CurPosition = 0;
7257 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00007258 break;
7259 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00007260 }
Jim Grosbach83ec8772011-11-10 23:42:14 +00007261 return false;
Jim Grosbachf8fce712011-08-11 17:35:48 +00007262}
7263
Jim Grosbach47a0d522011-08-16 20:45:50 +00007264unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
7265 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
7266 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00007267 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00007268 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00007269 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
7270 assert(MCID.hasOptionalDef() &&
7271 "optionally flag setting instruction missing optional def operand");
7272 assert(MCID.NumOperands == Inst.getNumOperands() &&
7273 "operand count mismatch!");
7274 // Find the optional-def operand (cc_out).
7275 unsigned OpNo;
7276 for (OpNo = 0;
7277 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
7278 ++OpNo)
7279 ;
7280 // If we're parsing Thumb1, reject it completely.
7281 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
7282 return Match_MnemonicFail;
7283 // If we're parsing Thumb2, which form is legal depends on whether we're
7284 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007285 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
7286 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00007287 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007288 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
7289 inITBlock())
7290 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00007291 }
Jim Grosbach194bd892011-08-16 22:20:01 +00007292 // Some high-register supporting Thumb1 encodings only allow both registers
7293 // to be from r0-r7 when in Thumb2.
7294 else if (Opc == ARM::tADDhirr && isThumbOne() &&
7295 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7296 isARMLowRegister(Inst.getOperand(2).getReg()))
7297 return Match_RequiresThumb2;
7298 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00007299 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00007300 isARMLowRegister(Inst.getOperand(0).getReg()) &&
7301 isARMLowRegister(Inst.getOperand(1).getReg()))
7302 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00007303 return Match_Success;
7304}
7305
Jim Grosbach14ce6fa2012-04-24 22:40:08 +00007306static const char *getSubtargetFeatureName(unsigned Val);
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007307bool ARMAsmParser::
7308MatchAndEmitInstruction(SMLoc IDLoc,
7309 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
7310 MCStreamer &Out) {
7311 MCInst Inst;
7312 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00007313 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00007314 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00007315 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00007316 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00007317 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00007318 // Context sensitive operand constraints aren't handled by the matcher,
7319 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00007320 if (validateInstruction(Inst, Operands)) {
7321 // Still progress the IT block, otherwise one wrong condition causes
7322 // nasty cascading errors.
7323 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00007324 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00007325 }
Jim Grosbach189610f2011-07-26 18:25:39 +00007326
Jim Grosbachf8fce712011-08-11 17:35:48 +00007327 // Some instructions need post-processing to, for example, tweak which
Jim Grosbach83ec8772011-11-10 23:42:14 +00007328 // encoding is selected. Loop on it while changes happen so the
7329 // individual transformations can chain off each other. E.g.,
7330 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
7331 while (processInstruction(Inst, Operands))
7332 ;
Jim Grosbachf8fce712011-08-11 17:35:48 +00007333
Jim Grosbacha1109882011-09-02 23:22:08 +00007334 // Only move forward at the very end so that everything in validate
7335 // and process gets a consistent answer about whether we're in an IT
7336 // block.
7337 forwardITPosition();
7338
Jim Grosbach74423e32012-01-25 19:52:01 +00007339 // ITasm is an ARM mode pseudo-instruction that just sets the ITblock and
7340 // doesn't actually encode.
7341 if (Inst.getOpcode() == ARM::ITasm)
7342 return false;
7343
Jim Grosbach42e6bd32012-01-26 23:20:15 +00007344 Inst.setLoc(IDLoc);
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007345 Out.EmitInstruction(Inst);
7346 return false;
Jim Grosbach14ce6fa2012-04-24 22:40:08 +00007347 case Match_MissingFeature: {
7348 assert(ErrorInfo && "Unknown missing feature!");
7349 // Special case the error message for the very common case where only
7350 // a single subtarget feature is missing (Thumb vs. ARM, e.g.).
7351 std::string Msg = "instruction requires:";
7352 unsigned Mask = 1;
7353 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
7354 if (ErrorInfo & Mask) {
7355 Msg += " ";
7356 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
7357 }
7358 Mask <<= 1;
7359 }
7360 return Error(IDLoc, Msg);
7361 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00007362 case Match_InvalidOperand: {
7363 SMLoc ErrorLoc = IDLoc;
7364 if (ErrorInfo != ~0U) {
7365 if (ErrorInfo >= Operands.size())
7366 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00007367
Chris Lattnere73d4f82010-10-28 21:41:58 +00007368 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
7369 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
7370 }
Jim Grosbach16c74252010-10-29 14:46:02 +00007371
Chris Lattnere73d4f82010-10-28 21:41:58 +00007372 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007373 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00007374 case Match_MnemonicFail:
Benjamin Kramer362a05a2012-04-15 17:04:27 +00007375 return Error(IDLoc, "invalid instruction",
7376 ((ARMOperand*)Operands[0])->getLocRange());
Daniel Dunbarb4129152011-02-04 17:12:23 +00007377 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00007378 // The converter function will have already emited a diagnostic.
7379 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007380 case Match_RequiresNotITBlock:
7381 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00007382 case Match_RequiresITBlock:
7383 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00007384 case Match_RequiresV6:
7385 return Error(IDLoc, "instruction variant requires ARMv6 or later");
7386 case Match_RequiresThumb2:
7387 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00007388 }
Jim Grosbach16c74252010-10-29 14:46:02 +00007389
Eric Christopherc223e2b2010-10-29 09:26:59 +00007390 llvm_unreachable("Implement any new match types added!");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007391}
7392
Jim Grosbach1355cf12011-07-26 17:10:22 +00007393/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007394bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
7395 StringRef IDVal = DirectiveID.getIdentifier();
7396 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007397 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007398 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007399 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach9a70df92011-12-07 18:04:19 +00007400 else if (IDVal == ".arm")
7401 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007402 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007403 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007404 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007405 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007406 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007407 return parseDirectiveSyntax(DirectiveID.getLoc());
Jim Grosbacha39cda72011-12-14 02:16:11 +00007408 else if (IDVal == ".unreq")
7409 return parseDirectiveUnreq(DirectiveID.getLoc());
Jason W Kimd7c9e082011-12-20 17:38:12 +00007410 else if (IDVal == ".arch")
7411 return parseDirectiveArch(DirectiveID.getLoc());
7412 else if (IDVal == ".eabi_attribute")
7413 return parseDirectiveEabiAttr(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007414 return true;
7415}
7416
Jim Grosbach1355cf12011-07-26 17:10:22 +00007417/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007418/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00007419bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007420 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7421 for (;;) {
7422 const MCExpr *Value;
7423 if (getParser().ParseExpression(Value))
7424 return true;
7425
Chris Lattneraaec2052010-01-19 19:46:13 +00007426 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007427
7428 if (getLexer().is(AsmToken::EndOfStatement))
7429 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00007430
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007431 // FIXME: Improve diagnostic.
7432 if (getLexer().isNot(AsmToken::Comma))
7433 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007434 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007435 }
7436 }
7437
Sean Callananb9a25b72010-01-19 20:27:46 +00007438 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007439 return false;
7440}
7441
Jim Grosbach1355cf12011-07-26 17:10:22 +00007442/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00007443/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00007444bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00007445 if (getLexer().isNot(AsmToken::EndOfStatement))
7446 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007447 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007448
Jim Grosbach9a70df92011-12-07 18:04:19 +00007449 if (!isThumb())
7450 SwitchMode();
7451 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
7452 return false;
7453}
7454
7455/// parseDirectiveARM
7456/// ::= .arm
7457bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
7458 if (getLexer().isNot(AsmToken::EndOfStatement))
7459 return Error(L, "unexpected token in directive");
7460 Parser.Lex();
7461
7462 if (isThumb())
7463 SwitchMode();
7464 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby515d5092009-10-15 20:48:48 +00007465 return false;
7466}
7467
Jim Grosbach1355cf12011-07-26 17:10:22 +00007468/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00007469/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00007470bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00007471 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
7472 bool isMachO = MAI.hasSubsectionsViaSymbols();
7473 StringRef Name;
Jim Grosbachde4d8392011-12-21 22:30:16 +00007474 bool needFuncName = true;
Rafael Espindola64695402011-05-16 16:17:21 +00007475
Jim Grosbachde4d8392011-12-21 22:30:16 +00007476 // Darwin asm has (optionally) function name after .thumb_func direction
Rafael Espindola64695402011-05-16 16:17:21 +00007477 // ELF doesn't
7478 if (isMachO) {
7479 const AsmToken &Tok = Parser.getTok();
Jim Grosbachde4d8392011-12-21 22:30:16 +00007480 if (Tok.isNot(AsmToken::EndOfStatement)) {
7481 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
7482 return Error(L, "unexpected token in .thumb_func directive");
7483 Name = Tok.getIdentifier();
7484 Parser.Lex(); // Consume the identifier token.
7485 needFuncName = false;
7486 }
Rafael Espindola64695402011-05-16 16:17:21 +00007487 }
7488
Jim Grosbachde4d8392011-12-21 22:30:16 +00007489 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby515d5092009-10-15 20:48:48 +00007490 return Error(L, "unexpected token in directive");
Jim Grosbachde4d8392011-12-21 22:30:16 +00007491
7492 // Eat the end of statement and any blank lines that follow.
7493 while (getLexer().is(AsmToken::EndOfStatement))
7494 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007495
Rafael Espindola64695402011-05-16 16:17:21 +00007496 // FIXME: assuming function name will be the line following .thumb_func
Jim Grosbachde4d8392011-12-21 22:30:16 +00007497 // We really should be checking the next symbol definition even if there's
7498 // stuff in between.
7499 if (needFuncName) {
Jim Grosbachd475f862011-11-10 20:48:53 +00007500 Name = Parser.getTok().getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00007501 }
7502
Jim Grosbach642fc9c2010-11-05 22:33:53 +00007503 // Mark symbol as a thumb symbol.
7504 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
7505 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00007506 return false;
7507}
7508
Jim Grosbach1355cf12011-07-26 17:10:22 +00007509/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00007510/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00007511bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00007512 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00007513 if (Tok.isNot(AsmToken::Identifier))
7514 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00007515 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00007516 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00007517 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00007518 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00007519 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00007520 else
7521 return Error(L, "unrecognized syntax mode in .syntax directive");
7522
7523 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00007524 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007525 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007526
7527 // TODO tell the MC streamer the mode
7528 // getParser().getStreamer().Emit???();
7529 return false;
7530}
7531
Jim Grosbach1355cf12011-07-26 17:10:22 +00007532/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00007533/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00007534bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00007535 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00007536 if (Tok.isNot(AsmToken::Integer))
7537 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00007538 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00007539 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00007540 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00007541 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00007542 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007543 else
7544 return Error(L, "invalid operand to .code directive");
7545
7546 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00007547 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007548 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007549
Evan Cheng32869202011-07-08 22:36:29 +00007550 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00007551 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00007552 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00007553 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00007554 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00007555 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00007556 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00007557 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00007558 }
Jim Grosbach2a301702010-11-05 22:40:53 +00007559
Kevin Enderby515d5092009-10-15 20:48:48 +00007560 return false;
7561}
7562
Jim Grosbacha39cda72011-12-14 02:16:11 +00007563/// parseDirectiveReq
7564/// ::= name .req registername
7565bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
7566 Parser.Lex(); // Eat the '.req' token.
7567 unsigned Reg;
7568 SMLoc SRegLoc, ERegLoc;
7569 if (ParseRegister(Reg, SRegLoc, ERegLoc)) {
7570 Parser.EatToEndOfStatement();
7571 return Error(SRegLoc, "register name expected");
7572 }
7573
7574 // Shouldn't be anything else.
7575 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
7576 Parser.EatToEndOfStatement();
7577 return Error(Parser.getTok().getLoc(),
7578 "unexpected input in .req directive.");
7579 }
7580
7581 Parser.Lex(); // Consume the EndOfStatement
7582
7583 if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg)
7584 return Error(SRegLoc, "redefinition of '" + Name +
7585 "' does not match original.");
7586
7587 return false;
7588}
7589
7590/// parseDirectiveUneq
7591/// ::= .unreq registername
7592bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
7593 if (Parser.getTok().isNot(AsmToken::Identifier)) {
7594 Parser.EatToEndOfStatement();
7595 return Error(L, "unexpected input in .unreq directive.");
7596 }
7597 RegisterReqs.erase(Parser.getTok().getIdentifier());
7598 Parser.Lex(); // Eat the identifier.
7599 return false;
7600}
7601
Jason W Kimd7c9e082011-12-20 17:38:12 +00007602/// parseDirectiveArch
7603/// ::= .arch token
7604bool ARMAsmParser::parseDirectiveArch(SMLoc L) {
7605 return true;
7606}
7607
7608/// parseDirectiveEabiAttr
7609/// ::= .eabi_attribute int, int
7610bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
7611 return true;
7612}
7613
Sean Callanan90b70972010-04-07 20:29:34 +00007614extern "C" void LLVMInitializeARMAsmLexer();
7615
Kevin Enderby9c41fa82009-10-30 22:55:57 +00007616/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007617extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00007618 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
7619 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00007620 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007621}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00007622
Chris Lattner0692ee62010-09-06 19:11:01 +00007623#define GET_REGISTER_MATCHER
Craig Topper8030e1a2012-04-25 06:56:34 +00007624#define GET_SUBTARGET_FEATURE_NAME
Chris Lattner0692ee62010-09-06 19:11:01 +00007625#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00007626#include "ARMGenAsmMatcher.inc"