blob: cbd9bdb77ca28e29d4390fe4eeba19bd15be8841 [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();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000917 return Val > -256 && Val < 256;
918 }
919 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000920 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000921 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000922 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000923 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
924 // Immediate offset in range [-255, 255].
925 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
926 if (!CE) return false;
927 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000928 // Special case, #-0 is INT32_MIN.
929 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000930 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000931 bool isAddrMode5() const {
Jim Grosbach681460f2011-11-01 01:24:45 +0000932 // If we have an immediate that's not a constant, treat it as a label
933 // reference needing a fixup. If it is a constant, it's something else
934 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000935 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach681460f2011-11-01 01:24:45 +0000936 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000937 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000938 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000939 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000940 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000941 if (!Memory.OffsetImm) return true;
942 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000943 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbach681460f2011-11-01 01:24:45 +0000944 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000945 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000946 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000947 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000948 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000949 return false;
950 return true;
951 }
952 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000953 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000954 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
955 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000956 return false;
957 return true;
958 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000959 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000960 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000961 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000962 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000963 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000964 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000965 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
966 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000967 return false;
968 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000969 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000970 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000971 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000972 return false;
973 return true;
974 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000975 bool isMemThumbRR() const {
976 // Thumb reg+reg addressing is simple. Just two registers, a base and
977 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000978 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000979 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000980 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000981 return isARMLowRegister(Memory.BaseRegNum) &&
982 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000983 }
984 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000985 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000986 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000987 return false;
988 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000989 if (!Memory.OffsetImm) return true;
990 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000991 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
992 }
Jim Grosbach38466302011-08-19 18:55:51 +0000993 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000994 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000995 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000996 return false;
997 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000998 if (!Memory.OffsetImm) return true;
999 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +00001000 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
1001 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001002 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +00001003 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +00001004 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001005 return false;
1006 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001007 if (!Memory.OffsetImm) return true;
1008 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001009 return Val >= 0 && Val <= 31;
1010 }
Jim Grosbachecd85892011-08-19 18:13:48 +00001011 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001012 if (!isMemory() || Memory.OffsetRegNum != 0 ||
1013 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +00001014 return false;
1015 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001016 if (!Memory.OffsetImm) return true;
1017 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +00001018 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001019 }
Jim Grosbacha77295d2011-09-08 22:07:06 +00001020 bool isMemImm8s4Offset() const {
Jim Grosbach2f196742011-12-19 23:06:24 +00001021 // If we have an immediate that's not a constant, treat it as a label
1022 // reference needing a fixup. If it is a constant, it's something else
1023 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001024 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach2f196742011-12-19 23:06:24 +00001025 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +00001026 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +00001027 return false;
1028 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001029 if (!Memory.OffsetImm) return true;
1030 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +00001031 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
1032 }
Jim Grosbachb6aed502011-09-09 18:37:27 +00001033 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001034 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +00001035 return false;
1036 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001037 if (!Memory.OffsetImm) return true;
1038 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +00001039 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
1040 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001041 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001042 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001043 return false;
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001044 // Base reg of PC isn't allowed for these encodings.
1045 if (Memory.BaseRegNum == ARM::PC) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001046 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001047 if (!Memory.OffsetImm) return true;
1048 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +00001049 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001050 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001051 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001052 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001053 return false;
1054 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001055 if (!Memory.OffsetImm) return true;
1056 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001057 return Val >= 0 && Val < 256;
1058 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001059 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001060 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001061 return false;
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001062 // Base reg of PC isn't allowed for these encodings.
1063 if (Memory.BaseRegNum == ARM::PC) return false;
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001064 // Immediate offset in range [-255, -1].
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001065 if (!Memory.OffsetImm) return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001066 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001067 return (Val == INT32_MIN) || (Val > -256 && Val < 0);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001068 }
1069 bool isMemUImm12Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001070 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001071 return false;
1072 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001073 if (!Memory.OffsetImm) return true;
1074 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001075 return (Val >= 0 && Val < 4096);
1076 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001077 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +00001078 // If we have an immediate that's not a constant, treat it as a label
1079 // reference needing a fixup. If it is a constant, it's something else
1080 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001081 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +00001082 return true;
1083
Jim Grosbach57dcb852011-10-11 17:29:55 +00001084 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001085 return false;
1086 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001087 if (!Memory.OffsetImm) return true;
1088 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +00001089 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001090 }
1091 bool isPostIdxImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001092 if (!isImm()) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001093 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1094 if (!CE) return false;
1095 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +00001096 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001097 }
Jim Grosbach2bd01182011-10-11 21:55:36 +00001098 bool isPostIdxImm8s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001099 if (!isImm()) return false;
Jim Grosbach2bd01182011-10-11 21:55:36 +00001100 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1101 if (!CE) return false;
1102 int64_t Val = CE->getValue();
1103 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1104 (Val == INT32_MIN);
1105 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001106
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001107 bool isMSRMask() const { return Kind == k_MSRMask; }
1108 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001109
Jim Grosbach0e387b22011-10-17 22:26:03 +00001110 // NEON operands.
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001111 bool isSingleSpacedVectorList() const {
1112 return Kind == k_VectorList && !VectorList.isDoubleSpaced;
1113 }
1114 bool isDoubleSpacedVectorList() const {
1115 return Kind == k_VectorList && VectorList.isDoubleSpaced;
1116 }
Jim Grosbach862019c2011-10-18 23:02:30 +00001117 bool isVecListOneD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001118 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach862019c2011-10-18 23:02:30 +00001119 return VectorList.Count == 1;
1120 }
1121
Jim Grosbach28f08c92012-03-05 19:33:30 +00001122 bool isVecListDPair() const {
1123 if (!isSingleSpacedVectorList()) return false;
1124 return (ARMMCRegisterClasses[ARM::DPairRegClassID]
1125 .contains(VectorList.RegNum));
1126 }
1127
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001128 bool isVecListThreeD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001129 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001130 return VectorList.Count == 3;
1131 }
1132
Jim Grosbachb6310312011-10-21 20:35:01 +00001133 bool isVecListFourD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001134 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachb6310312011-10-21 20:35:01 +00001135 return VectorList.Count == 4;
1136 }
1137
Jim Grosbachc3384c92012-03-05 21:43:40 +00001138 bool isVecListDPairSpaced() const {
Kevin Enderby9f2e1602012-03-20 17:41:51 +00001139 if (isSingleSpacedVectorList()) return false;
Jim Grosbachc3384c92012-03-05 21:43:40 +00001140 return (ARMMCRegisterClasses[ARM::DPairSpcRegClassID]
1141 .contains(VectorList.RegNum));
1142 }
1143
Jim Grosbachc387fc62012-01-23 23:20:46 +00001144 bool isVecListThreeQ() const {
1145 if (!isDoubleSpacedVectorList()) return false;
1146 return VectorList.Count == 3;
1147 }
1148
Jim Grosbach7945ead2012-01-24 00:43:12 +00001149 bool isVecListFourQ() const {
1150 if (!isDoubleSpacedVectorList()) return false;
1151 return VectorList.Count == 4;
1152 }
1153
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001154 bool isSingleSpacedVectorAllLanes() const {
1155 return Kind == k_VectorListAllLanes && !VectorList.isDoubleSpaced;
1156 }
1157 bool isDoubleSpacedVectorAllLanes() const {
1158 return Kind == k_VectorListAllLanes && VectorList.isDoubleSpaced;
1159 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00001160 bool isVecListOneDAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001161 if (!isSingleSpacedVectorAllLanes()) return false;
Jim Grosbach98b05a52011-11-30 01:09:44 +00001162 return VectorList.Count == 1;
1163 }
1164
Jim Grosbachc0fc4502012-03-06 22:01:44 +00001165 bool isVecListDPairAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001166 if (!isSingleSpacedVectorAllLanes()) return false;
Jim Grosbachc0fc4502012-03-06 22:01:44 +00001167 return (ARMMCRegisterClasses[ARM::DPairRegClassID]
1168 .contains(VectorList.RegNum));
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001169 }
1170
Jim Grosbach4d0983a2012-03-06 23:10:38 +00001171 bool isVecListDPairSpacedAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001172 if (!isDoubleSpacedVectorAllLanes()) return false;
Jim Grosbach13af2222011-11-30 18:21:25 +00001173 return VectorList.Count == 2;
1174 }
1175
Jim Grosbach5e59f7e2012-01-24 23:47:04 +00001176 bool isVecListThreeDAllLanes() const {
1177 if (!isSingleSpacedVectorAllLanes()) return false;
1178 return VectorList.Count == 3;
1179 }
1180
1181 bool isVecListThreeQAllLanes() const {
1182 if (!isDoubleSpacedVectorAllLanes()) return false;
1183 return VectorList.Count == 3;
1184 }
1185
Jim Grosbacha57a36a2012-01-25 00:01:08 +00001186 bool isVecListFourDAllLanes() const {
1187 if (!isSingleSpacedVectorAllLanes()) return false;
1188 return VectorList.Count == 4;
1189 }
1190
1191 bool isVecListFourQAllLanes() const {
1192 if (!isDoubleSpacedVectorAllLanes()) return false;
1193 return VectorList.Count == 4;
1194 }
1195
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001196 bool isSingleSpacedVectorIndexed() const {
1197 return Kind == k_VectorListIndexed && !VectorList.isDoubleSpaced;
1198 }
1199 bool isDoubleSpacedVectorIndexed() const {
1200 return Kind == k_VectorListIndexed && VectorList.isDoubleSpaced;
1201 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00001202 bool isVecListOneDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001203 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach7636bf62011-12-02 00:35:16 +00001204 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1205 }
1206
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001207 bool isVecListOneDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001208 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001209 return VectorList.Count == 1 && VectorList.LaneIndex <= 3;
1210 }
1211
1212 bool isVecListOneDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001213 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001214 return VectorList.Count == 1 && VectorList.LaneIndex <= 1;
1215 }
1216
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001217 bool isVecListTwoDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001218 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001219 return VectorList.Count == 2 && VectorList.LaneIndex <= 7;
1220 }
1221
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001222 bool isVecListTwoDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001223 if (!isSingleSpacedVectorIndexed()) return false;
1224 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1225 }
1226
1227 bool isVecListTwoQWordIndexed() const {
1228 if (!isDoubleSpacedVectorIndexed()) return false;
1229 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1230 }
1231
1232 bool isVecListTwoQHWordIndexed() const {
1233 if (!isDoubleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001234 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1235 }
1236
1237 bool isVecListTwoDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001238 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001239 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1240 }
1241
Jim Grosbach3a678af2012-01-23 21:53:26 +00001242 bool isVecListThreeDByteIndexed() const {
1243 if (!isSingleSpacedVectorIndexed()) return false;
1244 return VectorList.Count == 3 && VectorList.LaneIndex <= 7;
1245 }
1246
1247 bool isVecListThreeDHWordIndexed() const {
1248 if (!isSingleSpacedVectorIndexed()) return false;
1249 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1250 }
1251
1252 bool isVecListThreeQWordIndexed() const {
1253 if (!isDoubleSpacedVectorIndexed()) return false;
1254 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1255 }
1256
1257 bool isVecListThreeQHWordIndexed() const {
1258 if (!isDoubleSpacedVectorIndexed()) return false;
1259 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1260 }
1261
1262 bool isVecListThreeDWordIndexed() const {
1263 if (!isSingleSpacedVectorIndexed()) return false;
1264 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1265 }
1266
Jim Grosbache983a132012-01-24 18:37:25 +00001267 bool isVecListFourDByteIndexed() const {
1268 if (!isSingleSpacedVectorIndexed()) return false;
1269 return VectorList.Count == 4 && VectorList.LaneIndex <= 7;
1270 }
1271
1272 bool isVecListFourDHWordIndexed() const {
1273 if (!isSingleSpacedVectorIndexed()) return false;
1274 return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1275 }
1276
1277 bool isVecListFourQWordIndexed() const {
1278 if (!isDoubleSpacedVectorIndexed()) return false;
1279 return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1280 }
1281
1282 bool isVecListFourQHWordIndexed() const {
1283 if (!isDoubleSpacedVectorIndexed()) return false;
1284 return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1285 }
1286
1287 bool isVecListFourDWordIndexed() const {
1288 if (!isSingleSpacedVectorIndexed()) return false;
1289 return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1290 }
1291
Jim Grosbach460a9052011-10-07 23:56:00 +00001292 bool isVectorIndex8() const {
1293 if (Kind != k_VectorIndex) return false;
1294 return VectorIndex.Val < 8;
1295 }
1296 bool isVectorIndex16() const {
1297 if (Kind != k_VectorIndex) return false;
1298 return VectorIndex.Val < 4;
1299 }
1300 bool isVectorIndex32() const {
1301 if (Kind != k_VectorIndex) return false;
1302 return VectorIndex.Val < 2;
1303 }
1304
Jim Grosbach0e387b22011-10-17 22:26:03 +00001305 bool isNEONi8splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001306 if (!isImm()) return false;
Jim Grosbach0e387b22011-10-17 22:26:03 +00001307 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1308 // Must be a constant.
1309 if (!CE) return false;
1310 int64_t Value = CE->getValue();
1311 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1312 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +00001313 return Value >= 0 && Value < 256;
1314 }
Jim Grosbach460a9052011-10-07 23:56:00 +00001315
Jim Grosbachea461102011-10-17 23:09:09 +00001316 bool isNEONi16splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001317 if (!isImm()) return false;
Jim Grosbachea461102011-10-17 23:09:09 +00001318 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1319 // Must be a constant.
1320 if (!CE) return false;
1321 int64_t Value = CE->getValue();
1322 // i16 value in the range [0,255] or [0x0100, 0xff00]
1323 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1324 }
1325
Jim Grosbach6248a542011-10-18 00:22:00 +00001326 bool isNEONi32splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001327 if (!isImm()) return false;
Jim Grosbach6248a542011-10-18 00:22:00 +00001328 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1329 // Must be a constant.
1330 if (!CE) return false;
1331 int64_t Value = CE->getValue();
1332 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1333 return (Value >= 0 && Value < 256) ||
1334 (Value >= 0x0100 && Value <= 0xff00) ||
1335 (Value >= 0x010000 && Value <= 0xff0000) ||
1336 (Value >= 0x01000000 && Value <= 0xff000000);
1337 }
1338
1339 bool isNEONi32vmov() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001340 if (!isImm()) return false;
Jim Grosbach6248a542011-10-18 00:22:00 +00001341 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1342 // Must be a constant.
1343 if (!CE) return false;
1344 int64_t Value = CE->getValue();
1345 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1346 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1347 return (Value >= 0 && Value < 256) ||
1348 (Value >= 0x0100 && Value <= 0xff00) ||
1349 (Value >= 0x010000 && Value <= 0xff0000) ||
1350 (Value >= 0x01000000 && Value <= 0xff000000) ||
1351 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1352 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1353 }
Jim Grosbach9b087852011-12-19 23:51:07 +00001354 bool isNEONi32vmovNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001355 if (!isImm()) return false;
Jim Grosbach9b087852011-12-19 23:51:07 +00001356 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1357 // Must be a constant.
1358 if (!CE) return false;
1359 int64_t Value = ~CE->getValue();
1360 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1361 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1362 return (Value >= 0 && Value < 256) ||
1363 (Value >= 0x0100 && Value <= 0xff00) ||
1364 (Value >= 0x010000 && Value <= 0xff0000) ||
1365 (Value >= 0x01000000 && Value <= 0xff000000) ||
1366 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1367 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1368 }
Jim Grosbach6248a542011-10-18 00:22:00 +00001369
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001370 bool isNEONi64splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001371 if (!isImm()) return false;
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001372 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1373 // Must be a constant.
1374 if (!CE) return false;
1375 uint64_t Value = CE->getValue();
1376 // i64 value with each byte being either 0 or 0xff.
1377 for (unsigned i = 0; i < 8; ++i)
1378 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1379 return true;
1380 }
1381
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001382 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001383 // Add as immediates when possible. Null MCExpr = 0.
1384 if (Expr == 0)
1385 Inst.addOperand(MCOperand::CreateImm(0));
1386 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001387 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1388 else
1389 Inst.addOperand(MCOperand::CreateExpr(Expr));
1390 }
1391
Daniel Dunbar8462b302010-08-11 06:36:53 +00001392 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001393 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001394 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001395 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1396 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001397 }
1398
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001399 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1400 assert(N == 1 && "Invalid number of operands!");
1401 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1402 }
1403
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001404 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1405 assert(N == 1 && "Invalid number of operands!");
1406 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1407 }
1408
1409 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1410 assert(N == 1 && "Invalid number of operands!");
1411 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1412 }
1413
Jim Grosbach89df9962011-08-26 21:43:41 +00001414 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1415 assert(N == 1 && "Invalid number of operands!");
1416 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1417 }
1418
1419 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1420 assert(N == 1 && "Invalid number of operands!");
1421 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1422 }
1423
Jim Grosbachd67641b2010-12-06 18:21:12 +00001424 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1425 assert(N == 1 && "Invalid number of operands!");
1426 Inst.addOperand(MCOperand::CreateReg(getReg()));
1427 }
1428
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001429 void addRegOperands(MCInst &Inst, unsigned N) const {
1430 assert(N == 1 && "Invalid number of operands!");
1431 Inst.addOperand(MCOperand::CreateReg(getReg()));
1432 }
1433
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001434 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001435 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001436 assert(isRegShiftedReg() &&
1437 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001438 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1439 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001440 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001441 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001442 }
1443
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001444 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001445 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001446 assert(isRegShiftedImm() &&
1447 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001448 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001449 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001450 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001451 }
1452
Jim Grosbach580f4a92011-07-25 22:20:28 +00001453 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001454 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001455 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1456 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001457 }
1458
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001459 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001460 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001461 const SmallVectorImpl<unsigned> &RegList = getRegList();
1462 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001463 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1464 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001465 }
1466
Bill Wendling0f630752010-11-17 04:32:08 +00001467 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1468 addRegListOperands(Inst, N);
1469 }
1470
1471 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1472 addRegListOperands(Inst, N);
1473 }
1474
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001475 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1476 assert(N == 1 && "Invalid number of operands!");
1477 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1478 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1479 }
1480
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001481 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1482 assert(N == 1 && "Invalid number of operands!");
1483 // Munge the lsb/width into a bitfield mask.
1484 unsigned lsb = Bitfield.LSB;
1485 unsigned width = Bitfield.Width;
1486 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1487 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1488 (32 - (lsb + width)));
1489 Inst.addOperand(MCOperand::CreateImm(Mask));
1490 }
1491
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001492 void addImmOperands(MCInst &Inst, unsigned N) const {
1493 assert(N == 1 && "Invalid number of operands!");
1494 addExpr(Inst, getImm());
1495 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001496
Jim Grosbach4050bc42011-12-22 22:19:05 +00001497 void addFBits16Operands(MCInst &Inst, unsigned N) const {
1498 assert(N == 1 && "Invalid number of operands!");
1499 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1500 Inst.addOperand(MCOperand::CreateImm(16 - CE->getValue()));
1501 }
1502
1503 void addFBits32Operands(MCInst &Inst, unsigned N) const {
1504 assert(N == 1 && "Invalid number of operands!");
1505 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1506 Inst.addOperand(MCOperand::CreateImm(32 - CE->getValue()));
1507 }
1508
Jim Grosbach9d390362011-10-03 23:38:36 +00001509 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1510 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach51222d12012-01-20 18:09:51 +00001511 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1512 int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
1513 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach9d390362011-10-03 23:38:36 +00001514 }
1515
Jim Grosbacha77295d2011-09-08 22:07:06 +00001516 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1517 assert(N == 1 && "Invalid number of operands!");
1518 // FIXME: We really want to scale the value here, but the LDRD/STRD
1519 // instruction don't encode operands that way yet.
1520 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1521 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1522 }
1523
Jim Grosbach72f39f82011-08-24 21:22:15 +00001524 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1525 assert(N == 1 && "Invalid number of operands!");
1526 // The immediate is scaled by four in the encoding and is stored
1527 // in the MCInst as such. Lop off the low two bits here.
1528 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1529 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1530 }
1531
Jim Grosbach4e53fe82012-04-05 20:57:13 +00001532 void addImm0_508s4NegOperands(MCInst &Inst, unsigned N) const {
1533 assert(N == 1 && "Invalid number of operands!");
1534 // The immediate is scaled by four in the encoding and is stored
1535 // in the MCInst as such. Lop off the low two bits here.
1536 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1537 Inst.addOperand(MCOperand::CreateImm(-(CE->getValue() / 4)));
1538 }
1539
Jim Grosbach72f39f82011-08-24 21:22:15 +00001540 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1541 assert(N == 1 && "Invalid number of operands!");
1542 // The immediate is scaled by four in the encoding and is stored
1543 // in the MCInst as such. Lop off the low two bits here.
1544 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1545 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1546 }
1547
Jim Grosbachf4943352011-07-25 23:09:14 +00001548 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1549 assert(N == 1 && "Invalid number of operands!");
1550 // The constant encodes as the immediate-1, and we store in the instruction
1551 // the bits as encoded, so subtract off one here.
1552 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1553 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1554 }
1555
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001556 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1557 assert(N == 1 && "Invalid number of operands!");
1558 // The constant encodes as the immediate-1, and we store in the instruction
1559 // the bits as encoded, so subtract off one here.
1560 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1561 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1562 }
1563
Jim Grosbach70939ee2011-08-17 21:51:27 +00001564 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1565 assert(N == 1 && "Invalid number of operands!");
1566 // The constant encodes as the immediate, except for 32, which encodes as
1567 // zero.
1568 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1569 unsigned Imm = CE->getValue();
1570 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1571 }
1572
Jim Grosbachf6c05252011-07-21 17:23:04 +00001573 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1574 assert(N == 1 && "Invalid number of operands!");
1575 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1576 // the instruction as well.
1577 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1578 int Val = CE->getValue();
1579 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1580 }
1581
Jim Grosbach89a63372011-10-28 22:36:30 +00001582 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1583 assert(N == 1 && "Invalid number of operands!");
1584 // The operand is actually a t2_so_imm, but we have its bitwise
1585 // negation in the assembly source, so twiddle it here.
1586 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1587 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1588 }
1589
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001590 void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1591 assert(N == 1 && "Invalid number of operands!");
1592 // The operand is actually a t2_so_imm, but we have its
1593 // negation in the assembly source, so twiddle it here.
1594 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1595 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1596 }
1597
Jim Grosbach4e53fe82012-04-05 20:57:13 +00001598 void addImm0_4095NegOperands(MCInst &Inst, unsigned N) const {
1599 assert(N == 1 && "Invalid number of operands!");
1600 // The operand is actually an imm0_4095, but we have its
1601 // negation in the assembly source, so twiddle it here.
1602 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1603 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1604 }
1605
Jim Grosbache70ec842011-10-28 22:50:54 +00001606 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1607 assert(N == 1 && "Invalid number of operands!");
1608 // The operand is actually a so_imm, but we have its bitwise
1609 // negation in the assembly source, so twiddle it here.
1610 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1611 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1612 }
1613
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001614 void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
1615 assert(N == 1 && "Invalid number of operands!");
1616 // The operand is actually a so_imm, but we have its
1617 // negation in the assembly source, so twiddle it here.
1618 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1619 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1620 }
1621
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001622 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1623 assert(N == 1 && "Invalid number of operands!");
1624 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1625 }
1626
Jim Grosbach7ce05792011-08-03 23:50:40 +00001627 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1628 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001629 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001630 }
1631
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001632 void addMemPCRelImm12Operands(MCInst &Inst, unsigned N) const {
1633 assert(N == 1 && "Invalid number of operands!");
1634 int32_t Imm = Memory.OffsetImm->getValue();
1635 // FIXME: Handle #-0
1636 if (Imm == INT32_MIN) Imm = 0;
1637 Inst.addOperand(MCOperand::CreateImm(Imm));
1638 }
1639
Jim Grosbach57dcb852011-10-11 17:29:55 +00001640 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1641 assert(N == 2 && "Invalid number of operands!");
1642 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1643 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1644 }
1645
Jim Grosbach7ce05792011-08-03 23:50:40 +00001646 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1647 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001648 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1649 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001650 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1651 // Special case for #-0
1652 if (Val == INT32_MIN) Val = 0;
1653 if (Val < 0) Val = -Val;
1654 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1655 } else {
1656 // For register offset, we encode the shift type and negation flag
1657 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001658 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1659 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001660 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001661 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1662 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001663 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001664 }
1665
Jim Grosbach039c2e12011-08-04 23:01:30 +00001666 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1667 assert(N == 2 && "Invalid number of operands!");
1668 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1669 assert(CE && "non-constant AM2OffsetImm operand!");
1670 int32_t Val = CE->getValue();
1671 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1672 // Special case for #-0
1673 if (Val == INT32_MIN) Val = 0;
1674 if (Val < 0) Val = -Val;
1675 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1676 Inst.addOperand(MCOperand::CreateReg(0));
1677 Inst.addOperand(MCOperand::CreateImm(Val));
1678 }
1679
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001680 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1681 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001682 // If we have an immediate that's not a constant, treat it as a label
1683 // reference needing a fixup. If it is a constant, it's something else
1684 // and we reject it.
1685 if (isImm()) {
1686 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1687 Inst.addOperand(MCOperand::CreateReg(0));
1688 Inst.addOperand(MCOperand::CreateImm(0));
1689 return;
1690 }
1691
Jim Grosbache53c87b2011-10-11 15:59:20 +00001692 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1693 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001694 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1695 // Special case for #-0
1696 if (Val == INT32_MIN) Val = 0;
1697 if (Val < 0) Val = -Val;
1698 Val = ARM_AM::getAM3Opc(AddSub, Val);
1699 } else {
1700 // For register offset, we encode the shift type and negation flag
1701 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001702 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001703 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001704 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1705 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001706 Inst.addOperand(MCOperand::CreateImm(Val));
1707 }
1708
1709 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1710 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001711 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001712 int32_t Val =
1713 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1714 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1715 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001716 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001717 }
1718
1719 // Constant offset.
1720 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1721 int32_t Val = CE->getValue();
1722 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1723 // Special case for #-0
1724 if (Val == INT32_MIN) Val = 0;
1725 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001726 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001727 Inst.addOperand(MCOperand::CreateReg(0));
1728 Inst.addOperand(MCOperand::CreateImm(Val));
1729 }
1730
Jim Grosbach7ce05792011-08-03 23:50:40 +00001731 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1732 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach681460f2011-11-01 01:24:45 +00001733 // If we have an immediate that's not a constant, treat it as a label
1734 // reference needing a fixup. If it is a constant, it's something else
1735 // and we reject it.
1736 if (isImm()) {
1737 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1738 Inst.addOperand(MCOperand::CreateImm(0));
1739 return;
1740 }
1741
Jim Grosbach7ce05792011-08-03 23:50:40 +00001742 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001743 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001744 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1745 // Special case for #-0
1746 if (Val == INT32_MIN) Val = 0;
1747 if (Val < 0) Val = -Val;
1748 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001749 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001750 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001751 }
1752
Jim Grosbacha77295d2011-09-08 22:07:06 +00001753 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1754 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001755 // If we have an immediate that's not a constant, treat it as a label
1756 // reference needing a fixup. If it is a constant, it's something else
1757 // and we reject it.
1758 if (isImm()) {
1759 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1760 Inst.addOperand(MCOperand::CreateImm(0));
1761 return;
1762 }
1763
Jim Grosbache53c87b2011-10-11 15:59:20 +00001764 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1765 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001766 Inst.addOperand(MCOperand::CreateImm(Val));
1767 }
1768
Jim Grosbachb6aed502011-09-09 18:37:27 +00001769 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1770 assert(N == 2 && "Invalid number of operands!");
1771 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001772 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1773 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001774 Inst.addOperand(MCOperand::CreateImm(Val));
1775 }
1776
Jim Grosbach7ce05792011-08-03 23:50:40 +00001777 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1778 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001779 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1780 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001781 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001782 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001783
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001784 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1785 addMemImm8OffsetOperands(Inst, N);
1786 }
1787
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001788 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001789 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001790 }
1791
1792 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1793 assert(N == 2 && "Invalid number of operands!");
1794 // If this is an immediate, it's a label reference.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001795 if (isImm()) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001796 addExpr(Inst, getImm());
1797 Inst.addOperand(MCOperand::CreateImm(0));
1798 return;
1799 }
1800
1801 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001802 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1803 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001804 Inst.addOperand(MCOperand::CreateImm(Val));
1805 }
1806
Jim Grosbach7ce05792011-08-03 23:50:40 +00001807 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1808 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001809 // If this is an immediate, it's a label reference.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001810 if (isImm()) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001811 addExpr(Inst, getImm());
1812 Inst.addOperand(MCOperand::CreateImm(0));
1813 return;
1814 }
1815
1816 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001817 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1818 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001819 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001820 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001821
Jim Grosbach7f739be2011-09-19 22:21:13 +00001822 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1823 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001824 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1825 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001826 }
1827
1828 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1829 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001830 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1831 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001832 }
1833
Jim Grosbach7ce05792011-08-03 23:50:40 +00001834 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1835 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001836 unsigned Val =
1837 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1838 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001839 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1840 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001841 Inst.addOperand(MCOperand::CreateImm(Val));
1842 }
1843
Jim Grosbachab899c12011-09-07 23:10:15 +00001844 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1845 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001846 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1847 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1848 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001849 }
1850
Jim Grosbach7ce05792011-08-03 23:50:40 +00001851 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1852 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001853 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1854 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001855 }
1856
Jim Grosbach60f91a32011-08-19 17:55:24 +00001857 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1858 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001859 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1860 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001861 Inst.addOperand(MCOperand::CreateImm(Val));
1862 }
1863
Jim Grosbach38466302011-08-19 18:55:51 +00001864 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1865 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001866 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1867 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001868 Inst.addOperand(MCOperand::CreateImm(Val));
1869 }
1870
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001871 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1872 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001873 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1874 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001875 Inst.addOperand(MCOperand::CreateImm(Val));
1876 }
1877
Jim Grosbachecd85892011-08-19 18:13:48 +00001878 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1879 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001880 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1881 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001882 Inst.addOperand(MCOperand::CreateImm(Val));
1883 }
1884
Jim Grosbach7ce05792011-08-03 23:50:40 +00001885 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1886 assert(N == 1 && "Invalid number of operands!");
1887 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1888 assert(CE && "non-constant post-idx-imm8 operand!");
1889 int Imm = CE->getValue();
1890 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001891 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001892 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1893 Inst.addOperand(MCOperand::CreateImm(Imm));
1894 }
1895
Jim Grosbach2bd01182011-10-11 21:55:36 +00001896 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1897 assert(N == 1 && "Invalid number of operands!");
1898 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1899 assert(CE && "non-constant post-idx-imm8s4 operand!");
1900 int Imm = CE->getValue();
1901 bool isAdd = Imm >= 0;
1902 if (Imm == INT32_MIN) Imm = 0;
1903 // Immediate is scaled by 4.
1904 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1905 Inst.addOperand(MCOperand::CreateImm(Imm));
1906 }
1907
Jim Grosbach7ce05792011-08-03 23:50:40 +00001908 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1909 assert(N == 2 && "Invalid number of operands!");
1910 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001911 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1912 }
1913
1914 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1915 assert(N == 2 && "Invalid number of operands!");
1916 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1917 // The sign, shift type, and shift amount are encoded in a single operand
1918 // using the AM2 encoding helpers.
1919 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1920 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1921 PostIdxReg.ShiftTy);
1922 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001923 }
1924
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001925 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1926 assert(N == 1 && "Invalid number of operands!");
1927 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1928 }
1929
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001930 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1931 assert(N == 1 && "Invalid number of operands!");
1932 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1933 }
1934
Jim Grosbach6029b6d2011-11-29 23:51:09 +00001935 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach862019c2011-10-18 23:02:30 +00001936 assert(N == 1 && "Invalid number of operands!");
1937 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1938 }
1939
Jim Grosbach7636bf62011-12-02 00:35:16 +00001940 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1941 assert(N == 2 && "Invalid number of operands!");
1942 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1943 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1944 }
1945
Jim Grosbach460a9052011-10-07 23:56:00 +00001946 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1947 assert(N == 1 && "Invalid number of operands!");
1948 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1949 }
1950
1951 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1952 assert(N == 1 && "Invalid number of operands!");
1953 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1954 }
1955
1956 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1957 assert(N == 1 && "Invalid number of operands!");
1958 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1959 }
1960
Jim Grosbach0e387b22011-10-17 22:26:03 +00001961 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1962 assert(N == 1 && "Invalid number of operands!");
1963 // The immediate encodes the type of constant as well as the value.
1964 // Mask in that this is an i8 splat.
1965 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1966 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1967 }
1968
Jim Grosbachea461102011-10-17 23:09:09 +00001969 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1970 assert(N == 1 && "Invalid number of operands!");
1971 // The immediate encodes the type of constant as well as the value.
1972 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1973 unsigned Value = CE->getValue();
1974 if (Value >= 256)
1975 Value = (Value >> 8) | 0xa00;
1976 else
1977 Value |= 0x800;
1978 Inst.addOperand(MCOperand::CreateImm(Value));
1979 }
1980
Jim Grosbach6248a542011-10-18 00:22:00 +00001981 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1982 assert(N == 1 && "Invalid number of operands!");
1983 // The immediate encodes the type of constant as well as the value.
1984 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1985 unsigned Value = CE->getValue();
1986 if (Value >= 256 && Value <= 0xff00)
1987 Value = (Value >> 8) | 0x200;
1988 else if (Value > 0xffff && Value <= 0xff0000)
1989 Value = (Value >> 16) | 0x400;
1990 else if (Value > 0xffffff)
1991 Value = (Value >> 24) | 0x600;
1992 Inst.addOperand(MCOperand::CreateImm(Value));
1993 }
1994
1995 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1996 assert(N == 1 && "Invalid number of operands!");
1997 // The immediate encodes the type of constant as well as the value.
1998 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1999 unsigned Value = CE->getValue();
2000 if (Value >= 256 && Value <= 0xffff)
2001 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
2002 else if (Value > 0xffff && Value <= 0xffffff)
2003 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
2004 else if (Value > 0xffffff)
2005 Value = (Value >> 24) | 0x600;
2006 Inst.addOperand(MCOperand::CreateImm(Value));
2007 }
2008
Jim Grosbach9b087852011-12-19 23:51:07 +00002009 void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const {
2010 assert(N == 1 && "Invalid number of operands!");
2011 // The immediate encodes the type of constant as well as the value.
2012 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2013 unsigned Value = ~CE->getValue();
2014 if (Value >= 256 && Value <= 0xffff)
2015 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
2016 else if (Value > 0xffff && Value <= 0xffffff)
2017 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
2018 else if (Value > 0xffffff)
2019 Value = (Value >> 24) | 0x600;
2020 Inst.addOperand(MCOperand::CreateImm(Value));
2021 }
2022
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00002023 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
2024 assert(N == 1 && "Invalid number of operands!");
2025 // The immediate encodes the type of constant as well as the value.
2026 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2027 uint64_t Value = CE->getValue();
2028 unsigned Imm = 0;
2029 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
2030 Imm |= (Value & 1) << i;
2031 }
2032 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
2033 }
2034
Jim Grosbachb7f689b2011-07-13 15:34:57 +00002035 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00002036
Jim Grosbach89df9962011-08-26 21:43:41 +00002037 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002038 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00002039 Op->ITMask.Mask = Mask;
2040 Op->StartLoc = S;
2041 Op->EndLoc = S;
2042 return Op;
2043 }
2044
Chris Lattner3a697562010-10-28 17:20:03 +00002045 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002046 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00002047 Op->CC.Val = CC;
2048 Op->StartLoc = S;
2049 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00002050 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00002051 }
2052
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002053 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002054 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002055 Op->Cop.Val = CopVal;
2056 Op->StartLoc = S;
2057 Op->EndLoc = S;
2058 return Op;
2059 }
2060
2061 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002062 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002063 Op->Cop.Val = CopVal;
2064 Op->StartLoc = S;
2065 Op->EndLoc = S;
2066 return Op;
2067 }
2068
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002069 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
2070 ARMOperand *Op = new ARMOperand(k_CoprocOption);
2071 Op->Cop.Val = Val;
2072 Op->StartLoc = S;
2073 Op->EndLoc = E;
2074 return Op;
2075 }
2076
Jim Grosbachd67641b2010-12-06 18:21:12 +00002077 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002078 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00002079 Op->Reg.RegNum = RegNum;
2080 Op->StartLoc = S;
2081 Op->EndLoc = S;
2082 return Op;
2083 }
2084
Chris Lattner3a697562010-10-28 17:20:03 +00002085 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002086 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00002087 Op->Tok.Data = Str.data();
2088 Op->Tok.Length = Str.size();
2089 Op->StartLoc = S;
2090 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00002091 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002092 }
2093
Bill Wendling50d0f582010-11-18 23:43:05 +00002094 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002095 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00002096 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00002097 Op->StartLoc = S;
2098 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002099 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002100 }
2101
Jim Grosbache8606dc2011-07-13 17:50:29 +00002102 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
2103 unsigned SrcReg,
2104 unsigned ShiftReg,
2105 unsigned ShiftImm,
2106 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002107 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002108 Op->RegShiftedReg.ShiftTy = ShTy;
2109 Op->RegShiftedReg.SrcReg = SrcReg;
2110 Op->RegShiftedReg.ShiftReg = ShiftReg;
2111 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002112 Op->StartLoc = S;
2113 Op->EndLoc = E;
2114 return Op;
2115 }
2116
Owen Anderson92a20222011-07-21 18:54:16 +00002117 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
2118 unsigned SrcReg,
2119 unsigned ShiftImm,
2120 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002121 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002122 Op->RegShiftedImm.ShiftTy = ShTy;
2123 Op->RegShiftedImm.SrcReg = SrcReg;
2124 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00002125 Op->StartLoc = S;
2126 Op->EndLoc = E;
2127 return Op;
2128 }
2129
Jim Grosbach580f4a92011-07-25 22:20:28 +00002130 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002131 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002132 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00002133 Op->ShifterImm.isASR = isASR;
2134 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00002135 Op->StartLoc = S;
2136 Op->EndLoc = E;
2137 return Op;
2138 }
2139
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002140 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002141 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002142 Op->RotImm.Imm = Imm;
2143 Op->StartLoc = S;
2144 Op->EndLoc = E;
2145 return Op;
2146 }
2147
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002148 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
2149 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002150 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002151 Op->Bitfield.LSB = LSB;
2152 Op->Bitfield.Width = Width;
2153 Op->StartLoc = S;
2154 Op->EndLoc = E;
2155 return Op;
2156 }
2157
Bill Wendling7729e062010-11-09 22:44:22 +00002158 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00002159 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002160 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002161 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002162
Jim Grosbachd300b942011-09-13 22:56:44 +00002163 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002164 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00002165 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00002166 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002167 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002168
2169 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00002170 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002171 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00002172 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00002173 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002174 Op->StartLoc = StartLoc;
2175 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00002176 return Op;
2177 }
2178
Jim Grosbach862019c2011-10-18 23:02:30 +00002179 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002180 bool isDoubleSpaced, SMLoc S, SMLoc E) {
Jim Grosbach862019c2011-10-18 23:02:30 +00002181 ARMOperand *Op = new ARMOperand(k_VectorList);
2182 Op->VectorList.RegNum = RegNum;
2183 Op->VectorList.Count = Count;
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002184 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach862019c2011-10-18 23:02:30 +00002185 Op->StartLoc = S;
2186 Op->EndLoc = E;
2187 return Op;
2188 }
2189
Jim Grosbach98b05a52011-11-30 01:09:44 +00002190 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002191 bool isDoubleSpaced,
Jim Grosbach98b05a52011-11-30 01:09:44 +00002192 SMLoc S, SMLoc E) {
2193 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
2194 Op->VectorList.RegNum = RegNum;
2195 Op->VectorList.Count = Count;
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002196 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002197 Op->StartLoc = S;
2198 Op->EndLoc = E;
2199 return Op;
2200 }
2201
Jim Grosbach7636bf62011-12-02 00:35:16 +00002202 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002203 unsigned Index,
2204 bool isDoubleSpaced,
2205 SMLoc S, SMLoc E) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002206 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
2207 Op->VectorList.RegNum = RegNum;
2208 Op->VectorList.Count = Count;
2209 Op->VectorList.LaneIndex = Index;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002210 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002211 Op->StartLoc = S;
2212 Op->EndLoc = E;
2213 return Op;
2214 }
2215
Jim Grosbach460a9052011-10-07 23:56:00 +00002216 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
2217 MCContext &Ctx) {
2218 ARMOperand *Op = new ARMOperand(k_VectorIndex);
2219 Op->VectorIndex.Val = Idx;
2220 Op->StartLoc = S;
2221 Op->EndLoc = E;
2222 return Op;
2223 }
2224
Chris Lattner3a697562010-10-28 17:20:03 +00002225 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002226 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00002227 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00002228 Op->StartLoc = S;
2229 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002230 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00002231 }
2232
Jim Grosbach7ce05792011-08-03 23:50:40 +00002233 static ARMOperand *CreateMem(unsigned BaseRegNum,
2234 const MCConstantExpr *OffsetImm,
2235 unsigned OffsetRegNum,
2236 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002237 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00002238 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002239 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00002240 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002241 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00002242 Op->Memory.BaseRegNum = BaseRegNum;
2243 Op->Memory.OffsetImm = OffsetImm;
2244 Op->Memory.OffsetRegNum = OffsetRegNum;
2245 Op->Memory.ShiftType = ShiftType;
2246 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00002247 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00002248 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002249 Op->StartLoc = S;
2250 Op->EndLoc = E;
2251 return Op;
2252 }
Jim Grosbach16c74252010-10-29 14:46:02 +00002253
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002254 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
2255 ARM_AM::ShiftOpc ShiftTy,
2256 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002257 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002258 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002259 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002260 Op->PostIdxReg.isAdd = isAdd;
2261 Op->PostIdxReg.ShiftTy = ShiftTy;
2262 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00002263 Op->StartLoc = S;
2264 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002265 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002266 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002267
2268 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002269 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002270 Op->MBOpt.Val = Opt;
2271 Op->StartLoc = S;
2272 Op->EndLoc = S;
2273 return Op;
2274 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002275
2276 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002277 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002278 Op->IFlags.Val = IFlags;
2279 Op->StartLoc = S;
2280 Op->EndLoc = S;
2281 return Op;
2282 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002283
2284 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002285 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002286 Op->MMask.Val = MMask;
2287 Op->StartLoc = S;
2288 Op->EndLoc = S;
2289 return Op;
2290 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002291};
2292
2293} // end anonymous namespace.
2294
Jim Grosbachb7f689b2011-07-13 15:34:57 +00002295void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002296 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002297 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00002298 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002299 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002300 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00002301 OS << "<ccout " << getReg() << ">";
2302 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002303 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002304 static const char *MaskStr[] = {
2305 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2306 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2307 };
Jim Grosbach89df9962011-08-26 21:43:41 +00002308 assert((ITMask.Mask & 0xf) == ITMask.Mask);
2309 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2310 break;
2311 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002312 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002313 OS << "<coprocessor number: " << getCoproc() << ">";
2314 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002315 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002316 OS << "<coprocessor register: " << getCoproc() << ">";
2317 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002318 case k_CoprocOption:
2319 OS << "<coprocessor option: " << CoprocOption.Val << ">";
2320 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002321 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002322 OS << "<mask: " << getMSRMask() << ">";
2323 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002324 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002325 getImm()->print(OS);
2326 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002327 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002328 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2329 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002330 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002331 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00002332 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002333 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002334 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002335 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002336 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2337 << PostIdxReg.RegNum;
2338 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2339 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2340 << PostIdxReg.ShiftImm;
2341 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00002342 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002343 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002344 OS << "<ARM_PROC::";
2345 unsigned IFlags = getProcIFlags();
2346 for (int i=2; i >= 0; --i)
2347 if (IFlags & (1 << i))
2348 OS << ARM_PROC::IFlagsToString(1 << i);
2349 OS << ">";
2350 break;
2351 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002352 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00002353 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002354 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002355 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00002356 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2357 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00002358 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002359 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00002360 OS << "<so_reg_reg "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002361 << RegShiftedReg.SrcReg << " "
2362 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2363 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson00828302011-03-18 22:50:18 +00002364 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002365 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00002366 OS << "<so_reg_imm "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002367 << RegShiftedImm.SrcReg << " "
2368 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2369 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Anderson92a20222011-07-21 18:54:16 +00002370 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002371 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002372 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2373 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002374 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002375 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2376 << ", width: " << Bitfield.Width << ">";
2377 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002378 case k_RegisterList:
2379 case k_DPRRegisterList:
2380 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00002381 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002382
Bill Wendling5fa22a12010-11-09 23:28:44 +00002383 const SmallVectorImpl<unsigned> &RegList = getRegList();
2384 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002385 I = RegList.begin(), E = RegList.end(); I != E; ) {
2386 OS << *I;
2387 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002388 }
2389
2390 OS << ">";
2391 break;
2392 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002393 case k_VectorList:
2394 OS << "<vector_list " << VectorList.Count << " * "
2395 << VectorList.RegNum << ">";
2396 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002397 case k_VectorListAllLanes:
2398 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2399 << VectorList.RegNum << ">";
2400 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002401 case k_VectorListIndexed:
2402 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2403 << VectorList.Count << " * " << VectorList.RegNum << ">";
2404 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002405 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002406 OS << "'" << getToken() << "'";
2407 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00002408 case k_VectorIndex:
2409 OS << "<vectorindex " << getVectorIndex() << ">";
2410 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002411 }
2412}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00002413
2414/// @name Auto-generated Match Functions
2415/// {
2416
2417static unsigned MatchRegisterName(StringRef Name);
2418
2419/// }
2420
Bob Wilson69df7232011-02-03 21:46:10 +00002421bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2422 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbacha39cda72011-12-14 02:16:11 +00002423 StartLoc = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002424 RegNo = tryParseRegister();
Jim Grosbacha39cda72011-12-14 02:16:11 +00002425 EndLoc = Parser.getTok().getLoc();
Roman Divackybf755322011-01-27 17:14:22 +00002426
2427 return (RegNo == (unsigned)-1);
2428}
2429
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002430/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002431/// and if it is a register name the token is eaten and the register number is
2432/// returned. Otherwise return -1.
2433///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002434int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002435 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002436 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002437
Benjamin Kramer59085362011-11-06 20:37:06 +00002438 std::string lowerCase = Tok.getString().lower();
Owen Anderson0c9f2502011-01-13 22:50:36 +00002439 unsigned RegNum = MatchRegisterName(lowerCase);
2440 if (!RegNum) {
2441 RegNum = StringSwitch<unsigned>(lowerCase)
2442 .Case("r13", ARM::SP)
2443 .Case("r14", ARM::LR)
2444 .Case("r15", ARM::PC)
2445 .Case("ip", ARM::R12)
Jim Grosbach40e28552011-12-08 19:27:38 +00002446 // Additional register name aliases for 'gas' compatibility.
2447 .Case("a1", ARM::R0)
2448 .Case("a2", ARM::R1)
2449 .Case("a3", ARM::R2)
2450 .Case("a4", ARM::R3)
2451 .Case("v1", ARM::R4)
2452 .Case("v2", ARM::R5)
2453 .Case("v3", ARM::R6)
2454 .Case("v4", ARM::R7)
2455 .Case("v5", ARM::R8)
2456 .Case("v6", ARM::R9)
2457 .Case("v7", ARM::R10)
2458 .Case("v8", ARM::R11)
2459 .Case("sb", ARM::R9)
2460 .Case("sl", ARM::R10)
2461 .Case("fp", ARM::R11)
Owen Anderson0c9f2502011-01-13 22:50:36 +00002462 .Default(0);
2463 }
Jim Grosbacha39cda72011-12-14 02:16:11 +00002464 if (!RegNum) {
Jim Grosbachaee718b2011-12-20 23:11:00 +00002465 // Check for aliases registered via .req. Canonicalize to lower case.
2466 // That's more consistent since register names are case insensitive, and
2467 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2468 StringMap<unsigned>::const_iterator Entry = RegisterReqs.find(lowerCase);
Jim Grosbacha39cda72011-12-14 02:16:11 +00002469 // If no match, return failure.
2470 if (Entry == RegisterReqs.end())
2471 return -1;
2472 Parser.Lex(); // Eat identifier token.
2473 return Entry->getValue();
2474 }
Bob Wilson69df7232011-02-03 21:46:10 +00002475
Chris Lattnere5658fa2010-10-30 04:09:10 +00002476 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002477
Chris Lattnere5658fa2010-10-30 04:09:10 +00002478 return RegNum;
2479}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002480
Jim Grosbach19906722011-07-13 18:49:30 +00002481// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2482// If a recoverable error occurs, return 1. If an irrecoverable error
2483// occurs, return -1. An irrecoverable error is one where tokens have been
2484// consumed in the process of trying to parse the shifter (i.e., when it is
2485// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002486int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002487 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2488 SMLoc S = Parser.getTok().getLoc();
2489 const AsmToken &Tok = Parser.getTok();
2490 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2491
Benjamin Kramer59085362011-11-06 20:37:06 +00002492 std::string lowerCase = Tok.getString().lower();
Owen Anderson00828302011-03-18 22:50:18 +00002493 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbachaf4edea2011-12-07 23:40:58 +00002494 .Case("asl", ARM_AM::lsl)
Owen Anderson00828302011-03-18 22:50:18 +00002495 .Case("lsl", ARM_AM::lsl)
2496 .Case("lsr", ARM_AM::lsr)
2497 .Case("asr", ARM_AM::asr)
2498 .Case("ror", ARM_AM::ror)
2499 .Case("rrx", ARM_AM::rrx)
2500 .Default(ARM_AM::no_shift);
2501
2502 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002503 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002504
Jim Grosbache8606dc2011-07-13 17:50:29 +00002505 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002506
Jim Grosbache8606dc2011-07-13 17:50:29 +00002507 // The source register for the shift has already been added to the
2508 // operand list, so we need to pop it off and combine it into the shifted
2509 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002510 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002511 if (!PrevOp->isReg())
2512 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2513 int SrcReg = PrevOp->getReg();
2514 int64_t Imm = 0;
2515 int ShiftReg = 0;
2516 if (ShiftTy == ARM_AM::rrx) {
2517 // RRX Doesn't have an explicit shift amount. The encoder expects
2518 // the shift register to be the same as the source register. Seems odd,
2519 // but OK.
2520 ShiftReg = SrcReg;
2521 } else {
2522 // Figure out if this is shifted by a constant or a register (for non-RRX).
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00002523 if (Parser.getTok().is(AsmToken::Hash) ||
2524 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbache8606dc2011-07-13 17:50:29 +00002525 Parser.Lex(); // Eat hash.
2526 SMLoc ImmLoc = Parser.getTok().getLoc();
2527 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002528 if (getParser().ParseExpression(ShiftExpr)) {
2529 Error(ImmLoc, "invalid immediate shift value");
2530 return -1;
2531 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002532 // The expression must be evaluatable as an immediate.
2533 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002534 if (!CE) {
2535 Error(ImmLoc, "invalid immediate shift value");
2536 return -1;
2537 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002538 // Range check the immediate.
2539 // lsl, ror: 0 <= imm <= 31
2540 // lsr, asr: 0 <= imm <= 32
2541 Imm = CE->getValue();
2542 if (Imm < 0 ||
2543 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2544 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002545 Error(ImmLoc, "immediate shift value out of range");
2546 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002547 }
Jim Grosbachde626ad2011-12-22 17:37:00 +00002548 // shift by zero is a nop. Always send it through as lsl.
2549 // ('as' compatibility)
2550 if (Imm == 0)
2551 ShiftTy = ARM_AM::lsl;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002552 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002553 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002554 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002555 if (ShiftReg == -1) {
2556 Error (L, "expected immediate or register in shift operand");
2557 return -1;
2558 }
2559 } else {
2560 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002561 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002562 return -1;
2563 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002564 }
2565
Owen Anderson92a20222011-07-21 18:54:16 +00002566 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2567 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002568 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002569 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002570 else
2571 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2572 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002573
Jim Grosbach19906722011-07-13 18:49:30 +00002574 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002575}
2576
2577
Bill Wendling50d0f582010-11-18 23:43:05 +00002578/// Try to parse a register name. The token must be an Identifier when called.
2579/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2580/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002581///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002582/// TODO this is likely to change to allow different register types and or to
2583/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002584bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002585tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002586 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002587 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002588 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002589 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002590
Bill Wendling50d0f582010-11-18 23:43:05 +00002591 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002592
Chris Lattnere5658fa2010-10-30 04:09:10 +00002593 const AsmToken &ExclaimTok = Parser.getTok();
2594 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002595 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2596 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002597 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002598 return false;
2599 }
2600
2601 // Also check for an index operand. This is only legal for vector registers,
2602 // but that'll get caught OK in operand matching, so we don't need to
2603 // explicitly filter everything else out here.
2604 if (Parser.getTok().is(AsmToken::LBrac)) {
2605 SMLoc SIdx = Parser.getTok().getLoc();
2606 Parser.Lex(); // Eat left bracket token.
2607
2608 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002609 if (getParser().ParseExpression(ImmVal))
Jim Grosbach24dda212012-01-31 23:51:09 +00002610 return true;
Jim Grosbach460a9052011-10-07 23:56:00 +00002611 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbachef4d3eb2012-01-26 15:56:45 +00002612 if (!MCE)
2613 return TokError("immediate value expected for vector index");
Jim Grosbach460a9052011-10-07 23:56:00 +00002614
2615 SMLoc E = Parser.getTok().getLoc();
Jim Grosbachef4d3eb2012-01-26 15:56:45 +00002616 if (Parser.getTok().isNot(AsmToken::RBrac))
2617 return Error(E, "']' expected");
Jim Grosbach460a9052011-10-07 23:56:00 +00002618
2619 Parser.Lex(); // Eat right bracket token.
2620
2621 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2622 SIdx, E,
2623 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002624 }
2625
Bill Wendling50d0f582010-11-18 23:43:05 +00002626 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002627}
2628
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002629/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2630/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2631/// "c5", ...
2632static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002633 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2634 // but efficient.
2635 switch (Name.size()) {
David Blaikie4d6ccb52012-01-20 21:51:11 +00002636 default: return -1;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002637 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002638 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002639 return -1;
2640 switch (Name[1]) {
2641 default: return -1;
2642 case '0': return 0;
2643 case '1': return 1;
2644 case '2': return 2;
2645 case '3': return 3;
2646 case '4': return 4;
2647 case '5': return 5;
2648 case '6': return 6;
2649 case '7': return 7;
2650 case '8': return 8;
2651 case '9': return 9;
2652 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002653 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002654 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002655 return -1;
2656 switch (Name[2]) {
2657 default: return -1;
2658 case '0': return 10;
2659 case '1': return 11;
2660 case '2': return 12;
2661 case '3': return 13;
2662 case '4': return 14;
2663 case '5': return 15;
2664 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002665 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002666}
2667
Jim Grosbach89df9962011-08-26 21:43:41 +00002668/// parseITCondCode - Try to parse a condition code for an IT instruction.
2669ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2670parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2671 SMLoc S = Parser.getTok().getLoc();
2672 const AsmToken &Tok = Parser.getTok();
2673 if (!Tok.is(AsmToken::Identifier))
2674 return MatchOperand_NoMatch;
2675 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2676 .Case("eq", ARMCC::EQ)
2677 .Case("ne", ARMCC::NE)
2678 .Case("hs", ARMCC::HS)
2679 .Case("cs", ARMCC::HS)
2680 .Case("lo", ARMCC::LO)
2681 .Case("cc", ARMCC::LO)
2682 .Case("mi", ARMCC::MI)
2683 .Case("pl", ARMCC::PL)
2684 .Case("vs", ARMCC::VS)
2685 .Case("vc", ARMCC::VC)
2686 .Case("hi", ARMCC::HI)
2687 .Case("ls", ARMCC::LS)
2688 .Case("ge", ARMCC::GE)
2689 .Case("lt", ARMCC::LT)
2690 .Case("gt", ARMCC::GT)
2691 .Case("le", ARMCC::LE)
2692 .Case("al", ARMCC::AL)
2693 .Default(~0U);
2694 if (CC == ~0U)
2695 return MatchOperand_NoMatch;
2696 Parser.Lex(); // Eat the token.
2697
2698 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2699
2700 return MatchOperand_Success;
2701}
2702
Jim Grosbach43904292011-07-25 20:14:50 +00002703/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002704/// token must be an Identifier when called, and if it is a coprocessor
2705/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002706ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002707parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002708 SMLoc S = Parser.getTok().getLoc();
2709 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002710 if (Tok.isNot(AsmToken::Identifier))
2711 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002712
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002713 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002714 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002715 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002716
2717 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002718 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002719 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002720}
2721
Jim Grosbach43904292011-07-25 20:14:50 +00002722/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002723/// token must be an Identifier when called, and if it is a coprocessor
2724/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002725ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002726parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002727 SMLoc S = Parser.getTok().getLoc();
2728 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002729 if (Tok.isNot(AsmToken::Identifier))
2730 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002731
2732 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2733 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002734 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002735
2736 Parser.Lex(); // Eat identifier token.
2737 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002738 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002739}
2740
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002741/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2742/// coproc_option : '{' imm0_255 '}'
2743ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2744parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2745 SMLoc S = Parser.getTok().getLoc();
2746
2747 // If this isn't a '{', this isn't a coprocessor immediate operand.
2748 if (Parser.getTok().isNot(AsmToken::LCurly))
2749 return MatchOperand_NoMatch;
2750 Parser.Lex(); // Eat the '{'
2751
2752 const MCExpr *Expr;
2753 SMLoc Loc = Parser.getTok().getLoc();
2754 if (getParser().ParseExpression(Expr)) {
2755 Error(Loc, "illegal expression");
2756 return MatchOperand_ParseFail;
2757 }
2758 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2759 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2760 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2761 return MatchOperand_ParseFail;
2762 }
2763 int Val = CE->getValue();
2764
2765 // Check for and consume the closing '}'
2766 if (Parser.getTok().isNot(AsmToken::RCurly))
2767 return MatchOperand_ParseFail;
2768 SMLoc E = Parser.getTok().getLoc();
2769 Parser.Lex(); // Eat the '}'
2770
2771 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2772 return MatchOperand_Success;
2773}
2774
Jim Grosbachd0588e22011-09-14 18:08:35 +00002775// For register list parsing, we need to map from raw GPR register numbering
2776// to the enumeration values. The enumeration values aren't sorted by
2777// register number due to our using "sp", "lr" and "pc" as canonical names.
2778static unsigned getNextRegister(unsigned Reg) {
2779 // If this is a GPR, we need to do it manually, otherwise we can rely
2780 // on the sort ordering of the enumeration since the other reg-classes
2781 // are sane.
2782 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2783 return Reg + 1;
2784 switch(Reg) {
Craig Topperbc219812012-02-07 02:50:20 +00002785 default: llvm_unreachable("Invalid GPR number!");
Jim Grosbachd0588e22011-09-14 18:08:35 +00002786 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2787 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2788 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2789 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2790 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2791 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2792 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2793 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2794 }
2795}
2796
Jim Grosbachce485e72011-11-11 21:27:40 +00002797// Return the low-subreg of a given Q register.
2798static unsigned getDRegFromQReg(unsigned QReg) {
2799 switch (QReg) {
2800 default: llvm_unreachable("expected a Q register!");
2801 case ARM::Q0: return ARM::D0;
2802 case ARM::Q1: return ARM::D2;
2803 case ARM::Q2: return ARM::D4;
2804 case ARM::Q3: return ARM::D6;
2805 case ARM::Q4: return ARM::D8;
2806 case ARM::Q5: return ARM::D10;
2807 case ARM::Q6: return ARM::D12;
2808 case ARM::Q7: return ARM::D14;
2809 case ARM::Q8: return ARM::D16;
Jim Grosbach25e0a872011-11-15 21:01:30 +00002810 case ARM::Q9: return ARM::D18;
Jim Grosbachce485e72011-11-11 21:27:40 +00002811 case ARM::Q10: return ARM::D20;
2812 case ARM::Q11: return ARM::D22;
2813 case ARM::Q12: return ARM::D24;
2814 case ARM::Q13: return ARM::D26;
2815 case ARM::Q14: return ARM::D28;
2816 case ARM::Q15: return ARM::D30;
2817 }
2818}
2819
Jim Grosbachd0588e22011-09-14 18:08:35 +00002820/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002821bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002822parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002823 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002824 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002825 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002826 Parser.Lex(); // Eat '{' token.
2827 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002828
Jim Grosbachd0588e22011-09-14 18:08:35 +00002829 // Check the first register in the list to see what register class
2830 // this is a list of.
2831 int Reg = tryParseRegister();
2832 if (Reg == -1)
2833 return Error(RegLoc, "register expected");
2834
Jim Grosbachce485e72011-11-11 21:27:40 +00002835 // The reglist instructions have at most 16 registers, so reserve
2836 // space for that many.
2837 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2838
2839 // Allow Q regs and just interpret them as the two D sub-registers.
2840 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2841 Reg = getDRegFromQReg(Reg);
2842 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2843 ++Reg;
2844 }
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002845 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002846 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2847 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2848 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2849 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2850 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2851 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2852 else
2853 return Error(RegLoc, "invalid register in register list");
2854
Jim Grosbachce485e72011-11-11 21:27:40 +00002855 // Store the register.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002856 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002857
Jim Grosbachd0588e22011-09-14 18:08:35 +00002858 // This starts immediately after the first register token in the list,
2859 // so we can see either a comma or a minus (range separator) as a legal
2860 // next token.
2861 while (Parser.getTok().is(AsmToken::Comma) ||
2862 Parser.getTok().is(AsmToken::Minus)) {
2863 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache43862b2011-11-15 23:19:15 +00002864 Parser.Lex(); // Eat the minus.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002865 SMLoc EndLoc = Parser.getTok().getLoc();
2866 int EndReg = tryParseRegister();
2867 if (EndReg == -1)
2868 return Error(EndLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002869 // Allow Q regs and just interpret them as the two D sub-registers.
2870 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2871 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002872 // If the register is the same as the start reg, there's nothing
2873 // more to do.
2874 if (Reg == EndReg)
2875 continue;
2876 // The register must be in the same register class as the first.
2877 if (!RC->contains(EndReg))
2878 return Error(EndLoc, "invalid register in register list");
2879 // Ranges must go from low to high.
2880 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2881 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002882
Jim Grosbachd0588e22011-09-14 18:08:35 +00002883 // Add all the registers in the range to the register list.
2884 while (Reg != EndReg) {
2885 Reg = getNextRegister(Reg);
2886 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2887 }
2888 continue;
2889 }
2890 Parser.Lex(); // Eat the comma.
2891 RegLoc = Parser.getTok().getLoc();
2892 int OldReg = Reg;
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002893 const AsmToken RegTok = Parser.getTok();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002894 Reg = tryParseRegister();
2895 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002896 return Error(RegLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002897 // Allow Q regs and just interpret them as the two D sub-registers.
2898 bool isQReg = false;
2899 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2900 Reg = getDRegFromQReg(Reg);
2901 isQReg = true;
2902 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002903 // The register must be in the same register class as the first.
2904 if (!RC->contains(Reg))
2905 return Error(RegLoc, "invalid register in register list");
2906 // List must be monotonically increasing.
Jim Grosbachbe7cf2b2012-03-16 20:48:38 +00002907 if (getARMRegisterNumbering(Reg) < getARMRegisterNumbering(OldReg)) {
2908 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2909 Warning(RegLoc, "register list not in ascending order");
2910 else
2911 return Error(RegLoc, "register list not in ascending order");
2912 }
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002913 if (getARMRegisterNumbering(Reg) == getARMRegisterNumbering(OldReg)) {
2914 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
2915 ") in register list");
2916 continue;
2917 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002918 // VFP register lists must also be contiguous.
2919 // It's OK to use the enumeration values directly here rather, as the
2920 // VFP register classes have the enum sorted properly.
2921 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2922 Reg != OldReg + 1)
2923 return Error(RegLoc, "non-contiguous register range");
2924 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbachce485e72011-11-11 21:27:40 +00002925 if (isQReg)
2926 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002927 }
2928
Jim Grosbachd0588e22011-09-14 18:08:35 +00002929 SMLoc E = Parser.getTok().getLoc();
2930 if (Parser.getTok().isNot(AsmToken::RCurly))
2931 return Error(E, "'}' expected");
2932 Parser.Lex(); // Eat '}' token.
2933
Jim Grosbach27debd62011-12-13 21:48:29 +00002934 // Push the register list operand.
Bill Wendling50d0f582010-11-18 23:43:05 +00002935 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
Jim Grosbach27debd62011-12-13 21:48:29 +00002936
2937 // The ARM system instruction variants for LDM/STM have a '^' token here.
2938 if (Parser.getTok().is(AsmToken::Caret)) {
2939 Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
2940 Parser.Lex(); // Eat '^' token.
2941 }
2942
Bill Wendling50d0f582010-11-18 23:43:05 +00002943 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002944}
2945
Jim Grosbach98b05a52011-11-30 01:09:44 +00002946// Helper function to parse the lane index for vector lists.
2947ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach7636bf62011-12-02 00:35:16 +00002948parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2949 Index = 0; // Always return a defined index value.
Jim Grosbach98b05a52011-11-30 01:09:44 +00002950 if (Parser.getTok().is(AsmToken::LBrac)) {
2951 Parser.Lex(); // Eat the '['.
2952 if (Parser.getTok().is(AsmToken::RBrac)) {
2953 // "Dn[]" is the 'all lanes' syntax.
2954 LaneKind = AllLanes;
2955 Parser.Lex(); // Eat the ']'.
2956 return MatchOperand_Success;
2957 }
Jim Grosbachceee9842012-03-19 20:39:53 +00002958
2959 // There's an optional '#' token here. Normally there wouldn't be, but
2960 // inline assemble puts one in, and it's friendly to accept that.
2961 if (Parser.getTok().is(AsmToken::Hash))
2962 Parser.Lex(); // Eat the '#'
2963
Jim Grosbachc9313252011-12-21 01:19:23 +00002964 const MCExpr *LaneIndex;
2965 SMLoc Loc = Parser.getTok().getLoc();
2966 if (getParser().ParseExpression(LaneIndex)) {
2967 Error(Loc, "illegal expression");
2968 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002969 }
Jim Grosbachc9313252011-12-21 01:19:23 +00002970 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LaneIndex);
2971 if (!CE) {
2972 Error(Loc, "lane index must be empty or an integer");
2973 return MatchOperand_ParseFail;
2974 }
2975 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2976 Error(Parser.getTok().getLoc(), "']' expected");
2977 return MatchOperand_ParseFail;
2978 }
2979 Parser.Lex(); // Eat the ']'.
2980 int64_t Val = CE->getValue();
2981
2982 // FIXME: Make this range check context sensitive for .8, .16, .32.
2983 if (Val < 0 || Val > 7) {
2984 Error(Parser.getTok().getLoc(), "lane index out of range");
2985 return MatchOperand_ParseFail;
2986 }
2987 Index = Val;
2988 LaneKind = IndexedLane;
2989 return MatchOperand_Success;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002990 }
2991 LaneKind = NoLanes;
2992 return MatchOperand_Success;
2993}
2994
Jim Grosbach862019c2011-10-18 23:02:30 +00002995// parse a vector register list
2996ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2997parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002998 VectorLaneTy LaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002999 unsigned LaneIndex;
Jim Grosbach5c984e42011-11-15 21:45:55 +00003000 SMLoc S = Parser.getTok().getLoc();
3001 // As an extension (to match gas), support a plain D register or Q register
3002 // (without encosing curly braces) as a single or double entry list,
3003 // respectively.
3004 if (Parser.getTok().is(AsmToken::Identifier)) {
3005 int Reg = tryParseRegister();
3006 if (Reg == -1)
3007 return MatchOperand_NoMatch;
3008 SMLoc E = Parser.getTok().getLoc();
3009 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00003010 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00003011 if (Res != MatchOperand_Success)
3012 return Res;
3013 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003014 case NoLanes:
3015 E = Parser.getTok().getLoc();
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003016 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003017 break;
3018 case AllLanes:
3019 E = Parser.getTok().getLoc();
Jim Grosbach3471d4f2011-12-21 00:38:54 +00003020 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false,
3021 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003022 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003023 case IndexedLane:
3024 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00003025 LaneIndex,
3026 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00003027 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003028 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00003029 return MatchOperand_Success;
3030 }
3031 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
3032 Reg = getDRegFromQReg(Reg);
Jim Grosbach7636bf62011-12-02 00:35:16 +00003033 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00003034 if (Res != MatchOperand_Success)
3035 return Res;
3036 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003037 case NoLanes:
3038 E = Parser.getTok().getLoc();
Jim Grosbach28f08c92012-03-05 19:33:30 +00003039 Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0,
Jim Grosbachc0fc4502012-03-06 22:01:44 +00003040 &ARMMCRegisterClasses[ARM::DPairRegClassID]);
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003041 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003042 break;
3043 case AllLanes:
3044 E = Parser.getTok().getLoc();
Jim Grosbachc0fc4502012-03-06 22:01:44 +00003045 Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0,
3046 &ARMMCRegisterClasses[ARM::DPairRegClassID]);
Jim Grosbach3471d4f2011-12-21 00:38:54 +00003047 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, false,
3048 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003049 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003050 case IndexedLane:
3051 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00003052 LaneIndex,
3053 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00003054 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003055 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00003056 return MatchOperand_Success;
3057 }
3058 Error(S, "vector register expected");
3059 return MatchOperand_ParseFail;
3060 }
3061
3062 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbach862019c2011-10-18 23:02:30 +00003063 return MatchOperand_NoMatch;
3064
Jim Grosbach862019c2011-10-18 23:02:30 +00003065 Parser.Lex(); // Eat '{' token.
3066 SMLoc RegLoc = Parser.getTok().getLoc();
3067
3068 int Reg = tryParseRegister();
3069 if (Reg == -1) {
3070 Error(RegLoc, "register expected");
3071 return MatchOperand_ParseFail;
3072 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003073 unsigned Count = 1;
Jim Grosbach276ed032011-12-15 21:54:55 +00003074 int Spacing = 0;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003075 unsigned FirstReg = Reg;
3076 // The list is of D registers, but we also allow Q regs and just interpret
3077 // them as the two D sub-registers.
3078 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
3079 FirstReg = Reg = getDRegFromQReg(Reg);
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003080 Spacing = 1; // double-spacing requires explicit D registers, otherwise
3081 // it's ambiguous with four-register single spaced.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003082 ++Reg;
3083 ++Count;
3084 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00003085 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003086 return MatchOperand_ParseFail;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003087
Jim Grosbache43862b2011-11-15 23:19:15 +00003088 while (Parser.getTok().is(AsmToken::Comma) ||
3089 Parser.getTok().is(AsmToken::Minus)) {
3090 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003091 if (!Spacing)
3092 Spacing = 1; // Register range implies a single spaced list.
3093 else if (Spacing == 2) {
3094 Error(Parser.getTok().getLoc(),
3095 "sequential registers in double spaced list");
3096 return MatchOperand_ParseFail;
3097 }
Jim Grosbache43862b2011-11-15 23:19:15 +00003098 Parser.Lex(); // Eat the minus.
3099 SMLoc EndLoc = Parser.getTok().getLoc();
3100 int EndReg = tryParseRegister();
3101 if (EndReg == -1) {
3102 Error(EndLoc, "register expected");
3103 return MatchOperand_ParseFail;
3104 }
3105 // Allow Q regs and just interpret them as the two D sub-registers.
3106 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
3107 EndReg = getDRegFromQReg(EndReg) + 1;
3108 // If the register is the same as the start reg, there's nothing
3109 // more to do.
3110 if (Reg == EndReg)
3111 continue;
3112 // The register must be in the same register class as the first.
3113 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
3114 Error(EndLoc, "invalid register in register list");
3115 return MatchOperand_ParseFail;
3116 }
3117 // Ranges must go from low to high.
3118 if (Reg > EndReg) {
3119 Error(EndLoc, "bad range in register list");
3120 return MatchOperand_ParseFail;
3121 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00003122 // Parse the lane specifier if present.
3123 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003124 unsigned NextLaneIndex;
3125 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003126 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003127 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003128 Error(EndLoc, "mismatched lane index in register list");
3129 return MatchOperand_ParseFail;
3130 }
3131 EndLoc = Parser.getTok().getLoc();
Jim Grosbache43862b2011-11-15 23:19:15 +00003132
3133 // Add all the registers in the range to the register list.
3134 Count += EndReg - Reg;
3135 Reg = EndReg;
3136 continue;
3137 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003138 Parser.Lex(); // Eat the comma.
3139 RegLoc = Parser.getTok().getLoc();
3140 int OldReg = Reg;
3141 Reg = tryParseRegister();
3142 if (Reg == -1) {
3143 Error(RegLoc, "register expected");
3144 return MatchOperand_ParseFail;
3145 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003146 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00003147 // It's OK to use the enumeration values directly here rather, as the
3148 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003149 //
3150 // The list is of D registers, but we also allow Q regs and just interpret
3151 // them as the two D sub-registers.
3152 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003153 if (!Spacing)
3154 Spacing = 1; // Register range implies a single spaced list.
3155 else if (Spacing == 2) {
3156 Error(RegLoc,
3157 "invalid register in double-spaced list (must be 'D' register')");
3158 return MatchOperand_ParseFail;
3159 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003160 Reg = getDRegFromQReg(Reg);
3161 if (Reg != OldReg + 1) {
3162 Error(RegLoc, "non-contiguous register range");
3163 return MatchOperand_ParseFail;
3164 }
3165 ++Reg;
3166 Count += 2;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003167 // Parse the lane specifier if present.
3168 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003169 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003170 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003171 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003172 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003173 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003174 Error(EndLoc, "mismatched lane index in register list");
3175 return MatchOperand_ParseFail;
3176 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003177 continue;
3178 }
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003179 // Normal D register.
3180 // Figure out the register spacing (single or double) of the list if
3181 // we don't know it already.
3182 if (!Spacing)
3183 Spacing = 1 + (Reg == OldReg + 2);
3184
3185 // Just check that it's contiguous and keep going.
3186 if (Reg != OldReg + Spacing) {
Jim Grosbach862019c2011-10-18 23:02:30 +00003187 Error(RegLoc, "non-contiguous register range");
3188 return MatchOperand_ParseFail;
3189 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003190 ++Count;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003191 // Parse the lane specifier if present.
3192 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003193 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003194 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003195 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003196 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003197 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003198 Error(EndLoc, "mismatched lane index in register list");
3199 return MatchOperand_ParseFail;
3200 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003201 }
3202
3203 SMLoc E = Parser.getTok().getLoc();
3204 if (Parser.getTok().isNot(AsmToken::RCurly)) {
3205 Error(E, "'}' expected");
3206 return MatchOperand_ParseFail;
3207 }
3208 Parser.Lex(); // Eat '}' token.
3209
Jim Grosbach98b05a52011-11-30 01:09:44 +00003210 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003211 case NoLanes:
Jim Grosbachc0fc4502012-03-06 22:01:44 +00003212 // Two-register operands have been converted to the
Jim Grosbachc3384c92012-03-05 21:43:40 +00003213 // composite register classes.
3214 if (Count == 2) {
3215 const MCRegisterClass *RC = (Spacing == 1) ?
3216 &ARMMCRegisterClasses[ARM::DPairRegClassID] :
3217 &ARMMCRegisterClasses[ARM::DPairSpcRegClassID];
3218 FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC);
3219 }
Jim Grosbach28f08c92012-03-05 19:33:30 +00003220
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003221 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count,
3222 (Spacing == 2), S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003223 break;
3224 case AllLanes:
Jim Grosbachc0fc4502012-03-06 22:01:44 +00003225 // Two-register operands have been converted to the
3226 // composite register classes.
Jim Grosbach4d0983a2012-03-06 23:10:38 +00003227 if (Count == 2) {
3228 const MCRegisterClass *RC = (Spacing == 1) ?
3229 &ARMMCRegisterClasses[ARM::DPairRegClassID] :
3230 &ARMMCRegisterClasses[ARM::DPairSpcRegClassID];
Jim Grosbachc0fc4502012-03-06 22:01:44 +00003231 FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC);
3232 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00003233 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00003234 (Spacing == 2),
Jim Grosbach98b05a52011-11-30 01:09:44 +00003235 S, E));
3236 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003237 case IndexedLane:
3238 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00003239 LaneIndex,
3240 (Spacing == 2),
3241 S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00003242 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003243 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003244 return MatchOperand_Success;
3245}
3246
Jim Grosbach43904292011-07-25 20:14:50 +00003247/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00003248ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003249parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003250 SMLoc S = Parser.getTok().getLoc();
3251 const AsmToken &Tok = Parser.getTok();
3252 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3253 StringRef OptStr = Tok.getString();
3254
3255 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
3256 .Case("sy", ARM_MB::SY)
3257 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003258 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003259 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003260 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003261 .Case("ishst", ARM_MB::ISHST)
3262 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003263 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003264 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003265 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003266 .Case("osh", ARM_MB::OSH)
3267 .Case("oshst", ARM_MB::OSHST)
3268 .Default(~0U);
3269
3270 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00003271 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003272
3273 Parser.Lex(); // Eat identifier token.
3274 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00003275 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003276}
3277
Jim Grosbach43904292011-07-25 20:14:50 +00003278/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003279ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003280parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003281 SMLoc S = Parser.getTok().getLoc();
3282 const AsmToken &Tok = Parser.getTok();
3283 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3284 StringRef IFlagsStr = Tok.getString();
3285
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003286 // An iflags string of "none" is interpreted to mean that none of the AIF
3287 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003288 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003289 if (IFlagsStr != "none") {
3290 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
3291 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
3292 .Case("a", ARM_PROC::A)
3293 .Case("i", ARM_PROC::I)
3294 .Case("f", ARM_PROC::F)
3295 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003296
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003297 // If some specific iflag is already set, it means that some letter is
3298 // present more than once, this is not acceptable.
3299 if (Flag == ~0U || (IFlags & Flag))
3300 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003301
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003302 IFlags |= Flag;
3303 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003304 }
3305
3306 Parser.Lex(); // Eat identifier token.
3307 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
3308 return MatchOperand_Success;
3309}
3310
Jim Grosbach43904292011-07-25 20:14:50 +00003311/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003312ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003313parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003314 SMLoc S = Parser.getTok().getLoc();
3315 const AsmToken &Tok = Parser.getTok();
3316 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3317 StringRef Mask = Tok.getString();
3318
James Molloyacad68d2011-09-28 14:21:38 +00003319 if (isMClass()) {
3320 // See ARMv6-M 10.1.1
Jim Grosbachb84ad4a2012-03-15 21:34:14 +00003321 std::string Name = Mask.lower();
3322 unsigned FlagsVal = StringSwitch<unsigned>(Name)
James Molloyacad68d2011-09-28 14:21:38 +00003323 .Case("apsr", 0)
3324 .Case("iapsr", 1)
3325 .Case("eapsr", 2)
3326 .Case("xpsr", 3)
3327 .Case("ipsr", 5)
3328 .Case("epsr", 6)
3329 .Case("iepsr", 7)
3330 .Case("msp", 8)
3331 .Case("psp", 9)
3332 .Case("primask", 16)
3333 .Case("basepri", 17)
3334 .Case("basepri_max", 18)
3335 .Case("faultmask", 19)
3336 .Case("control", 20)
3337 .Default(~0U);
Jim Grosbach18c8d122011-12-22 17:17:10 +00003338
James Molloyacad68d2011-09-28 14:21:38 +00003339 if (FlagsVal == ~0U)
3340 return MatchOperand_NoMatch;
3341
3342 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
3343 // basepri, basepri_max and faultmask only valid for V7m.
3344 return MatchOperand_NoMatch;
Jim Grosbach18c8d122011-12-22 17:17:10 +00003345
James Molloyacad68d2011-09-28 14:21:38 +00003346 Parser.Lex(); // Eat identifier token.
3347 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3348 return MatchOperand_Success;
3349 }
3350
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003351 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
3352 size_t Start = 0, Next = Mask.find('_');
3353 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00003354 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003355 if (Next != StringRef::npos)
3356 Flags = Mask.slice(Next+1, Mask.size());
3357
3358 // FlagsVal contains the complete mask:
3359 // 3-0: Mask
3360 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3361 unsigned FlagsVal = 0;
3362
3363 if (SpecReg == "apsr") {
3364 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00003365 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003366 .Case("g", 0x4) // same as CPSR_s
3367 .Case("nzcvqg", 0xc) // same as CPSR_fs
3368 .Default(~0U);
3369
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003370 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003371 if (!Flags.empty())
3372 return MatchOperand_NoMatch;
3373 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00003374 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003375 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003376 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Jim Grosbachb657a902012-04-05 03:17:53 +00003377 // cpsr_all is an alias for cpsr_fc, as is plain cpsr.
3378 if (Flags == "all" || Flags == "")
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00003379 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003380 for (int i = 0, e = Flags.size(); i != e; ++i) {
3381 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
3382 .Case("c", 1)
3383 .Case("x", 2)
3384 .Case("s", 4)
3385 .Case("f", 8)
3386 .Default(~0U);
3387
3388 // If some specific flag is already set, it means that some letter is
3389 // present more than once, this is not acceptable.
3390 if (FlagsVal == ~0U || (FlagsVal & Flag))
3391 return MatchOperand_NoMatch;
3392 FlagsVal |= Flag;
3393 }
3394 } else // No match for special register.
3395 return MatchOperand_NoMatch;
3396
Owen Anderson7784f1d2011-10-21 18:43:28 +00003397 // Special register without flags is NOT equivalent to "fc" flags.
3398 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3399 // two lines would enable gas compatibility at the expense of breaking
3400 // round-tripping.
3401 //
3402 // if (!FlagsVal)
3403 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003404
3405 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3406 if (SpecReg == "spsr")
3407 FlagsVal |= 16;
3408
3409 Parser.Lex(); // Eat identifier token.
3410 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3411 return MatchOperand_Success;
3412}
3413
Jim Grosbachf6c05252011-07-21 17:23:04 +00003414ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3415parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3416 int Low, int High) {
3417 const AsmToken &Tok = Parser.getTok();
3418 if (Tok.isNot(AsmToken::Identifier)) {
3419 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3420 return MatchOperand_ParseFail;
3421 }
3422 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00003423 std::string LowerOp = Op.lower();
3424 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00003425 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3426 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3427 return MatchOperand_ParseFail;
3428 }
3429 Parser.Lex(); // Eat shift type token.
3430
3431 // There must be a '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003432 if (Parser.getTok().isNot(AsmToken::Hash) &&
3433 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbachf6c05252011-07-21 17:23:04 +00003434 Error(Parser.getTok().getLoc(), "'#' expected");
3435 return MatchOperand_ParseFail;
3436 }
3437 Parser.Lex(); // Eat hash token.
3438
3439 const MCExpr *ShiftAmount;
3440 SMLoc Loc = Parser.getTok().getLoc();
3441 if (getParser().ParseExpression(ShiftAmount)) {
3442 Error(Loc, "illegal expression");
3443 return MatchOperand_ParseFail;
3444 }
3445 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3446 if (!CE) {
3447 Error(Loc, "constant expression expected");
3448 return MatchOperand_ParseFail;
3449 }
3450 int Val = CE->getValue();
3451 if (Val < Low || Val > High) {
3452 Error(Loc, "immediate value out of range");
3453 return MatchOperand_ParseFail;
3454 }
3455
3456 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3457
3458 return MatchOperand_Success;
3459}
3460
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003461ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3462parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3463 const AsmToken &Tok = Parser.getTok();
3464 SMLoc S = Tok.getLoc();
3465 if (Tok.isNot(AsmToken::Identifier)) {
3466 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3467 return MatchOperand_ParseFail;
3468 }
3469 int Val = StringSwitch<int>(Tok.getString())
3470 .Case("be", 1)
3471 .Case("le", 0)
3472 .Default(-1);
3473 Parser.Lex(); // Eat the token.
3474
3475 if (Val == -1) {
3476 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3477 return MatchOperand_ParseFail;
3478 }
3479 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3480 getContext()),
3481 S, Parser.getTok().getLoc()));
3482 return MatchOperand_Success;
3483}
3484
Jim Grosbach580f4a92011-07-25 22:20:28 +00003485/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3486/// instructions. Legal values are:
3487/// lsl #n 'n' in [0,31]
3488/// asr #n 'n' in [1,32]
3489/// n == 32 encoded as n == 0.
3490ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3491parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3492 const AsmToken &Tok = Parser.getTok();
3493 SMLoc S = Tok.getLoc();
3494 if (Tok.isNot(AsmToken::Identifier)) {
3495 Error(S, "shift operator 'asr' or 'lsl' expected");
3496 return MatchOperand_ParseFail;
3497 }
3498 StringRef ShiftName = Tok.getString();
3499 bool isASR;
3500 if (ShiftName == "lsl" || ShiftName == "LSL")
3501 isASR = false;
3502 else if (ShiftName == "asr" || ShiftName == "ASR")
3503 isASR = true;
3504 else {
3505 Error(S, "shift operator 'asr' or 'lsl' expected");
3506 return MatchOperand_ParseFail;
3507 }
3508 Parser.Lex(); // Eat the operator.
3509
3510 // A '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003511 if (Parser.getTok().isNot(AsmToken::Hash) &&
3512 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach580f4a92011-07-25 22:20:28 +00003513 Error(Parser.getTok().getLoc(), "'#' expected");
3514 return MatchOperand_ParseFail;
3515 }
3516 Parser.Lex(); // Eat hash token.
3517
3518 const MCExpr *ShiftAmount;
3519 SMLoc E = Parser.getTok().getLoc();
3520 if (getParser().ParseExpression(ShiftAmount)) {
3521 Error(E, "malformed shift expression");
3522 return MatchOperand_ParseFail;
3523 }
3524 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3525 if (!CE) {
3526 Error(E, "shift amount must be an immediate");
3527 return MatchOperand_ParseFail;
3528 }
3529
3530 int64_t Val = CE->getValue();
3531 if (isASR) {
3532 // Shift amount must be in [1,32]
3533 if (Val < 1 || Val > 32) {
3534 Error(E, "'asr' shift amount must be in range [1,32]");
3535 return MatchOperand_ParseFail;
3536 }
Owen Anderson0afa0092011-09-26 21:06:22 +00003537 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3538 if (isThumb() && Val == 32) {
3539 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3540 return MatchOperand_ParseFail;
3541 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00003542 if (Val == 32) Val = 0;
3543 } else {
3544 // Shift amount must be in [1,32]
3545 if (Val < 0 || Val > 31) {
3546 Error(E, "'lsr' shift amount must be in range [0,31]");
3547 return MatchOperand_ParseFail;
3548 }
3549 }
3550
3551 E = Parser.getTok().getLoc();
3552 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3553
3554 return MatchOperand_Success;
3555}
3556
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003557/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3558/// of instructions. Legal values are:
3559/// ror #n 'n' in {0, 8, 16, 24}
3560ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3561parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3562 const AsmToken &Tok = Parser.getTok();
3563 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00003564 if (Tok.isNot(AsmToken::Identifier))
3565 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003566 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00003567 if (ShiftName != "ror" && ShiftName != "ROR")
3568 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003569 Parser.Lex(); // Eat the operator.
3570
3571 // A '#' and a rotate amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003572 if (Parser.getTok().isNot(AsmToken::Hash) &&
3573 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003574 Error(Parser.getTok().getLoc(), "'#' expected");
3575 return MatchOperand_ParseFail;
3576 }
3577 Parser.Lex(); // Eat hash token.
3578
3579 const MCExpr *ShiftAmount;
3580 SMLoc E = Parser.getTok().getLoc();
3581 if (getParser().ParseExpression(ShiftAmount)) {
3582 Error(E, "malformed rotate expression");
3583 return MatchOperand_ParseFail;
3584 }
3585 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3586 if (!CE) {
3587 Error(E, "rotate amount must be an immediate");
3588 return MatchOperand_ParseFail;
3589 }
3590
3591 int64_t Val = CE->getValue();
3592 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3593 // normally, zero is represented in asm by omitting the rotate operand
3594 // entirely.
3595 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3596 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3597 return MatchOperand_ParseFail;
3598 }
3599
3600 E = Parser.getTok().getLoc();
3601 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3602
3603 return MatchOperand_Success;
3604}
3605
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003606ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3607parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3608 SMLoc S = Parser.getTok().getLoc();
3609 // The bitfield descriptor is really two operands, the LSB and the width.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003610 if (Parser.getTok().isNot(AsmToken::Hash) &&
3611 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003612 Error(Parser.getTok().getLoc(), "'#' expected");
3613 return MatchOperand_ParseFail;
3614 }
3615 Parser.Lex(); // Eat hash token.
3616
3617 const MCExpr *LSBExpr;
3618 SMLoc E = Parser.getTok().getLoc();
3619 if (getParser().ParseExpression(LSBExpr)) {
3620 Error(E, "malformed immediate expression");
3621 return MatchOperand_ParseFail;
3622 }
3623 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3624 if (!CE) {
3625 Error(E, "'lsb' operand must be an immediate");
3626 return MatchOperand_ParseFail;
3627 }
3628
3629 int64_t LSB = CE->getValue();
3630 // The LSB must be in the range [0,31]
3631 if (LSB < 0 || LSB > 31) {
3632 Error(E, "'lsb' operand must be in the range [0,31]");
3633 return MatchOperand_ParseFail;
3634 }
3635 E = Parser.getTok().getLoc();
3636
3637 // Expect another immediate operand.
3638 if (Parser.getTok().isNot(AsmToken::Comma)) {
3639 Error(Parser.getTok().getLoc(), "too few operands");
3640 return MatchOperand_ParseFail;
3641 }
3642 Parser.Lex(); // Eat hash token.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003643 if (Parser.getTok().isNot(AsmToken::Hash) &&
3644 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003645 Error(Parser.getTok().getLoc(), "'#' expected");
3646 return MatchOperand_ParseFail;
3647 }
3648 Parser.Lex(); // Eat hash token.
3649
3650 const MCExpr *WidthExpr;
3651 if (getParser().ParseExpression(WidthExpr)) {
3652 Error(E, "malformed immediate expression");
3653 return MatchOperand_ParseFail;
3654 }
3655 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3656 if (!CE) {
3657 Error(E, "'width' operand must be an immediate");
3658 return MatchOperand_ParseFail;
3659 }
3660
3661 int64_t Width = CE->getValue();
3662 // The LSB must be in the range [1,32-lsb]
3663 if (Width < 1 || Width > 32 - LSB) {
3664 Error(E, "'width' operand must be in the range [1,32-lsb]");
3665 return MatchOperand_ParseFail;
3666 }
3667 E = Parser.getTok().getLoc();
3668
3669 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3670
3671 return MatchOperand_Success;
3672}
3673
Jim Grosbach7ce05792011-08-03 23:50:40 +00003674ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3675parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3676 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003677 // postidx_reg := '+' register {, shift}
3678 // | '-' register {, shift}
3679 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003680
3681 // This method must return MatchOperand_NoMatch without consuming any tokens
3682 // in the case where there is no match, as other alternatives take other
3683 // parse methods.
3684 AsmToken Tok = Parser.getTok();
3685 SMLoc S = Tok.getLoc();
3686 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003687 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003688 int Reg = -1;
3689 if (Tok.is(AsmToken::Plus)) {
3690 Parser.Lex(); // Eat the '+' token.
3691 haveEaten = true;
3692 } else if (Tok.is(AsmToken::Minus)) {
3693 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003694 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003695 haveEaten = true;
3696 }
3697 if (Parser.getTok().is(AsmToken::Identifier))
3698 Reg = tryParseRegister();
3699 if (Reg == -1) {
3700 if (!haveEaten)
3701 return MatchOperand_NoMatch;
3702 Error(Parser.getTok().getLoc(), "register expected");
3703 return MatchOperand_ParseFail;
3704 }
3705 SMLoc E = Parser.getTok().getLoc();
3706
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003707 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3708 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003709 if (Parser.getTok().is(AsmToken::Comma)) {
3710 Parser.Lex(); // Eat the ','.
3711 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3712 return MatchOperand_ParseFail;
3713 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003714
3715 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3716 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003717
3718 return MatchOperand_Success;
3719}
3720
Jim Grosbach251bf252011-08-10 21:56:18 +00003721ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3722parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3723 // Check for a post-index addressing register operand. Specifically:
3724 // am3offset := '+' register
3725 // | '-' register
3726 // | register
3727 // | # imm
3728 // | # + imm
3729 // | # - imm
3730
3731 // This method must return MatchOperand_NoMatch without consuming any tokens
3732 // in the case where there is no match, as other alternatives take other
3733 // parse methods.
3734 AsmToken Tok = Parser.getTok();
3735 SMLoc S = Tok.getLoc();
3736
3737 // Do immediates first, as we always parse those if we have a '#'.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003738 if (Parser.getTok().is(AsmToken::Hash) ||
3739 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach251bf252011-08-10 21:56:18 +00003740 Parser.Lex(); // Eat the '#'.
3741 // Explicitly look for a '-', as we need to encode negative zero
3742 // differently.
3743 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3744 const MCExpr *Offset;
3745 if (getParser().ParseExpression(Offset))
3746 return MatchOperand_ParseFail;
3747 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3748 if (!CE) {
3749 Error(S, "constant expression expected");
3750 return MatchOperand_ParseFail;
3751 }
3752 SMLoc E = Tok.getLoc();
3753 // Negative zero is encoded as the flag value INT32_MIN.
3754 int32_t Val = CE->getValue();
3755 if (isNegative && Val == 0)
3756 Val = INT32_MIN;
3757
3758 Operands.push_back(
3759 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3760
3761 return MatchOperand_Success;
3762 }
3763
3764
3765 bool haveEaten = false;
3766 bool isAdd = true;
3767 int Reg = -1;
3768 if (Tok.is(AsmToken::Plus)) {
3769 Parser.Lex(); // Eat the '+' token.
3770 haveEaten = true;
3771 } else if (Tok.is(AsmToken::Minus)) {
3772 Parser.Lex(); // Eat the '-' token.
3773 isAdd = false;
3774 haveEaten = true;
3775 }
3776 if (Parser.getTok().is(AsmToken::Identifier))
3777 Reg = tryParseRegister();
3778 if (Reg == -1) {
3779 if (!haveEaten)
3780 return MatchOperand_NoMatch;
3781 Error(Parser.getTok().getLoc(), "register expected");
3782 return MatchOperand_ParseFail;
3783 }
3784 SMLoc E = Parser.getTok().getLoc();
3785
3786 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3787 0, S, E));
3788
3789 return MatchOperand_Success;
3790}
3791
Jim Grosbacha77295d2011-09-08 22:07:06 +00003792/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3793/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3794/// when they refer multiple MIOperands inside a single one.
3795bool ARMAsmParser::
3796cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3797 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3798 // Rt, Rt2
3799 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3800 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3801 // Create a writeback register dummy placeholder.
3802 Inst.addOperand(MCOperand::CreateReg(0));
3803 // addr
3804 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3805 // pred
3806 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3807 return true;
3808}
3809
3810/// cvtT2StrdPre - Convert parsed operands to MCInst.
3811/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3812/// when they refer multiple MIOperands inside a single one.
3813bool ARMAsmParser::
3814cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3815 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3816 // Create a writeback register dummy placeholder.
3817 Inst.addOperand(MCOperand::CreateReg(0));
3818 // Rt, Rt2
3819 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3820 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3821 // addr
3822 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3823 // pred
3824 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3825 return true;
3826}
3827
Jim Grosbacheeec0252011-09-08 00:39:19 +00003828/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3829/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3830/// when they refer multiple MIOperands inside a single one.
3831bool ARMAsmParser::
3832cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3833 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3834 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3835
3836 // Create a writeback register dummy placeholder.
3837 Inst.addOperand(MCOperand::CreateImm(0));
3838
3839 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3840 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3841 return true;
3842}
3843
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003844/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3845/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3846/// when they refer multiple MIOperands inside a single one.
3847bool ARMAsmParser::
3848cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3849 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3850 // Create a writeback register dummy placeholder.
3851 Inst.addOperand(MCOperand::CreateImm(0));
3852 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3853 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3854 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3855 return true;
3856}
3857
Jim Grosbach1355cf12011-07-26 17:10:22 +00003858/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003859/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3860/// when they refer multiple MIOperands inside a single one.
3861bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003862cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003863 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3864 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3865
3866 // Create a writeback register dummy placeholder.
3867 Inst.addOperand(MCOperand::CreateImm(0));
3868
Jim Grosbach7ce05792011-08-03 23:50:40 +00003869 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003870 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3871 return true;
3872}
3873
Owen Anderson9ab0f252011-08-26 20:43:14 +00003874/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3875/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3876/// when they refer multiple MIOperands inside a single one.
3877bool ARMAsmParser::
3878cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3879 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3880 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3881
3882 // Create a writeback register dummy placeholder.
3883 Inst.addOperand(MCOperand::CreateImm(0));
3884
3885 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3886 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3887 return true;
3888}
3889
3890
Jim Grosbach548340c2011-08-11 19:22:40 +00003891/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3892/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3893/// when they refer multiple MIOperands inside a single one.
3894bool ARMAsmParser::
3895cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3896 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3897 // Create a writeback register dummy placeholder.
3898 Inst.addOperand(MCOperand::CreateImm(0));
3899 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3900 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3901 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3902 return true;
3903}
3904
Jim Grosbach1355cf12011-07-26 17:10:22 +00003905/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003906/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3907/// when they refer multiple MIOperands inside a single one.
3908bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003909cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003910 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3911 // Create a writeback register dummy placeholder.
3912 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003913 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3914 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3915 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003916 return true;
3917}
3918
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003919/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3920/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3921/// when they refer multiple MIOperands inside a single one.
3922bool ARMAsmParser::
3923cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3924 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3925 // Create a writeback register dummy placeholder.
3926 Inst.addOperand(MCOperand::CreateImm(0));
3927 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3928 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3929 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3930 return true;
3931}
3932
Jim Grosbach7ce05792011-08-03 23:50:40 +00003933/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3934/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3935/// when they refer multiple MIOperands inside a single one.
3936bool ARMAsmParser::
3937cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3938 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3939 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003940 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003941 // Create a writeback register dummy placeholder.
3942 Inst.addOperand(MCOperand::CreateImm(0));
3943 // addr
3944 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3945 // offset
3946 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3947 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003948 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3949 return true;
3950}
3951
Jim Grosbach7ce05792011-08-03 23:50:40 +00003952/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003953/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3954/// when they refer multiple MIOperands inside a single one.
3955bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003956cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3957 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3958 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003959 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003960 // Create a writeback register dummy placeholder.
3961 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003962 // addr
3963 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3964 // offset
3965 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3966 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003967 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3968 return true;
3969}
3970
Jim Grosbach7ce05792011-08-03 23:50:40 +00003971/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003972/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3973/// when they refer multiple MIOperands inside a single one.
3974bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003975cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3976 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003977 // Create a writeback register dummy placeholder.
3978 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003979 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003980 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003981 // addr
3982 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3983 // offset
3984 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3985 // pred
3986 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3987 return true;
3988}
3989
3990/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3991/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3992/// when they refer multiple MIOperands inside a single one.
3993bool ARMAsmParser::
3994cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3995 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3996 // Create a writeback register dummy placeholder.
3997 Inst.addOperand(MCOperand::CreateImm(0));
3998 // Rt
3999 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
4000 // addr
4001 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
4002 // offset
4003 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
4004 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00004005 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4006 return true;
4007}
4008
Jim Grosbach2fd2b872011-08-10 20:29:19 +00004009/// cvtLdrdPre - Convert parsed operands to MCInst.
4010/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4011/// when they refer multiple MIOperands inside a single one.
4012bool ARMAsmParser::
4013cvtLdrdPre(MCInst &Inst, unsigned Opcode,
4014 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4015 // Rt, Rt2
4016 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
4017 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
4018 // Create a writeback register dummy placeholder.
4019 Inst.addOperand(MCOperand::CreateImm(0));
4020 // addr
4021 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
4022 // pred
4023 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4024 return true;
4025}
4026
Jim Grosbach14605d12011-08-11 20:28:23 +00004027/// cvtStrdPre - Convert parsed operands to MCInst.
4028/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4029/// when they refer multiple MIOperands inside a single one.
4030bool ARMAsmParser::
4031cvtStrdPre(MCInst &Inst, unsigned Opcode,
4032 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4033 // Create a writeback register dummy placeholder.
4034 Inst.addOperand(MCOperand::CreateImm(0));
4035 // Rt, Rt2
4036 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
4037 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
4038 // addr
4039 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
4040 // pred
4041 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4042 return true;
4043}
4044
Jim Grosbach623a4542011-08-10 22:42:16 +00004045/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
4046/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4047/// when they refer multiple MIOperands inside a single one.
4048bool ARMAsmParser::
4049cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
4050 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4051 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
4052 // Create a writeback register dummy placeholder.
4053 Inst.addOperand(MCOperand::CreateImm(0));
4054 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
4055 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4056 return true;
4057}
4058
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004059/// cvtThumbMultiple- Convert parsed operands to MCInst.
4060/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4061/// when they refer multiple MIOperands inside a single one.
4062bool ARMAsmParser::
4063cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
4064 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4065 // The second source operand must be the same register as the destination
4066 // operand.
4067 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00004068 (((ARMOperand*)Operands[3])->getReg() !=
4069 ((ARMOperand*)Operands[5])->getReg()) &&
4070 (((ARMOperand*)Operands[3])->getReg() !=
4071 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004072 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00004073 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004074 return false;
4075 }
4076 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
4077 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach1b332862011-11-10 22:10:12 +00004078 // If we have a three-operand form, make sure to set Rn to be the operand
4079 // that isn't the same as Rd.
4080 unsigned RegOp = 4;
4081 if (Operands.size() == 6 &&
4082 ((ARMOperand*)Operands[4])->getReg() ==
4083 ((ARMOperand*)Operands[3])->getReg())
4084 RegOp = 5;
4085 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
4086 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004087 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
4088
4089 return true;
4090}
Jim Grosbach623a4542011-08-10 22:42:16 +00004091
Jim Grosbach12431322011-10-24 22:16:58 +00004092bool ARMAsmParser::
4093cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
4094 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4095 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004096 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00004097 // Create a writeback register dummy placeholder.
4098 Inst.addOperand(MCOperand::CreateImm(0));
4099 // Vn
4100 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4101 // pred
4102 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4103 return true;
4104}
4105
4106bool ARMAsmParser::
4107cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
4108 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4109 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004110 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00004111 // Create a writeback register dummy placeholder.
4112 Inst.addOperand(MCOperand::CreateImm(0));
4113 // Vn
4114 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4115 // Vm
4116 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4117 // pred
4118 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4119 return true;
4120}
4121
Jim Grosbach4334e032011-10-31 21:50:31 +00004122bool ARMAsmParser::
4123cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
4124 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4125 // Create a writeback register dummy placeholder.
4126 Inst.addOperand(MCOperand::CreateImm(0));
4127 // Vn
4128 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4129 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004130 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00004131 // pred
4132 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4133 return true;
4134}
4135
4136bool ARMAsmParser::
4137cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
4138 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4139 // Create a writeback register dummy placeholder.
4140 Inst.addOperand(MCOperand::CreateImm(0));
4141 // Vn
4142 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4143 // Vm
4144 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4145 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004146 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00004147 // pred
4148 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4149 return true;
4150}
4151
Bill Wendlinge7176102010-11-06 22:36:58 +00004152/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004153/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00004154bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00004155parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00004156 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00004157 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00004158 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00004159 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004160 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004161
Sean Callanan18b83232010-01-19 21:44:56 +00004162 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00004163 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00004164 if (BaseRegNum == -1)
4165 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004166
Daniel Dunbar05710932011-01-18 05:34:17 +00004167 // The next token must either be a comma or a closing bracket.
4168 const AsmToken &Tok = Parser.getTok();
4169 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004170 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00004171
Jim Grosbach7ce05792011-08-03 23:50:40 +00004172 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00004173 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004174 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004175
Jim Grosbach7ce05792011-08-03 23:50:40 +00004176 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004177 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00004178
Jim Grosbachfb12f352011-09-19 18:42:21 +00004179 // If there's a pre-indexing writeback marker, '!', just add it as a token
4180 // operand. It's rather odd, but syntactically valid.
4181 if (Parser.getTok().is(AsmToken::Exclaim)) {
4182 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4183 Parser.Lex(); // Eat the '!'.
4184 }
4185
Jim Grosbach7ce05792011-08-03 23:50:40 +00004186 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004187 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004188
Jim Grosbach7ce05792011-08-03 23:50:40 +00004189 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
4190 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004191
Jim Grosbach57dcb852011-10-11 17:29:55 +00004192 // If we have a ':', it's an alignment specifier.
4193 if (Parser.getTok().is(AsmToken::Colon)) {
4194 Parser.Lex(); // Eat the ':'.
4195 E = Parser.getTok().getLoc();
4196
4197 const MCExpr *Expr;
4198 if (getParser().ParseExpression(Expr))
4199 return true;
4200
4201 // The expression has to be a constant. Memory references with relocations
4202 // don't come through here, as they use the <label> forms of the relevant
4203 // instructions.
4204 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4205 if (!CE)
4206 return Error (E, "constant expression expected");
4207
4208 unsigned Align = 0;
4209 switch (CE->getValue()) {
4210 default:
Jim Grosbacheeaf1c12011-12-19 18:31:43 +00004211 return Error(E,
4212 "alignment specifier must be 16, 32, 64, 128, or 256 bits");
4213 case 16: Align = 2; break;
4214 case 32: Align = 4; break;
Jim Grosbach57dcb852011-10-11 17:29:55 +00004215 case 64: Align = 8; break;
4216 case 128: Align = 16; break;
4217 case 256: Align = 32; break;
4218 }
4219
4220 // Now we should have the closing ']'
4221 E = Parser.getTok().getLoc();
4222 if (Parser.getTok().isNot(AsmToken::RBrac))
4223 return Error(E, "']' expected");
4224 Parser.Lex(); // Eat right bracket token.
4225
4226 // Don't worry about range checking the value here. That's handled by
4227 // the is*() predicates.
4228 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
4229 ARM_AM::no_shift, 0, Align,
4230 false, S, E));
4231
4232 // If there's a pre-indexing writeback marker, '!', just add it as a token
4233 // operand.
4234 if (Parser.getTok().is(AsmToken::Exclaim)) {
4235 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4236 Parser.Lex(); // Eat the '!'.
4237 }
4238
4239 return false;
4240 }
4241
4242 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004243 // offset. Be friendly and also accept a plain integer (without a leading
4244 // hash) for gas compatibility.
4245 if (Parser.getTok().is(AsmToken::Hash) ||
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004246 Parser.getTok().is(AsmToken::Dollar) ||
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004247 Parser.getTok().is(AsmToken::Integer)) {
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004248 if (Parser.getTok().isNot(AsmToken::Integer))
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004249 Parser.Lex(); // Eat the '#'.
Jim Grosbach7ce05792011-08-03 23:50:40 +00004250 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004251
Owen Anderson0da10cf2011-08-29 19:36:44 +00004252 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00004253 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004254 if (getParser().ParseExpression(Offset))
4255 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004256
4257 // The expression has to be a constant. Memory references with relocations
4258 // don't come through here, as they use the <label> forms of the relevant
4259 // instructions.
4260 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
4261 if (!CE)
4262 return Error (E, "constant expression expected");
4263
Owen Anderson0da10cf2011-08-29 19:36:44 +00004264 // If the constant was #-0, represent it as INT32_MIN.
4265 int32_t Val = CE->getValue();
4266 if (isNegative && Val == 0)
4267 CE = MCConstantExpr::Create(INT32_MIN, getContext());
4268
Jim Grosbach7ce05792011-08-03 23:50:40 +00004269 // Now we should have the closing ']'
4270 E = Parser.getTok().getLoc();
4271 if (Parser.getTok().isNot(AsmToken::RBrac))
4272 return Error(E, "']' expected");
4273 Parser.Lex(); // Eat right bracket token.
4274
4275 // Don't worry about range checking the value here. That's handled by
4276 // the is*() predicates.
4277 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004278 ARM_AM::no_shift, 0, 0,
4279 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00004280
4281 // If there's a pre-indexing writeback marker, '!', just add it as a token
4282 // operand.
4283 if (Parser.getTok().is(AsmToken::Exclaim)) {
4284 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4285 Parser.Lex(); // Eat the '!'.
4286 }
4287
4288 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004289 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004290
4291 // The register offset is optionally preceded by a '+' or '-'
4292 bool isNegative = false;
4293 if (Parser.getTok().is(AsmToken::Minus)) {
4294 isNegative = true;
4295 Parser.Lex(); // Eat the '-'.
4296 } else if (Parser.getTok().is(AsmToken::Plus)) {
4297 // Nothing to do.
4298 Parser.Lex(); // Eat the '+'.
4299 }
4300
4301 E = Parser.getTok().getLoc();
4302 int OffsetRegNum = tryParseRegister();
4303 if (OffsetRegNum == -1)
4304 return Error(E, "register expected");
4305
4306 // If there's a shift operator, handle it.
4307 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004308 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004309 if (Parser.getTok().is(AsmToken::Comma)) {
4310 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004311 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004312 return true;
4313 }
4314
4315 // Now we should have the closing ']'
4316 E = Parser.getTok().getLoc();
4317 if (Parser.getTok().isNot(AsmToken::RBrac))
4318 return Error(E, "']' expected");
4319 Parser.Lex(); // Eat right bracket token.
4320
4321 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004322 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00004323 S, E));
4324
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00004325 // If there's a pre-indexing writeback marker, '!', just add it as a token
4326 // operand.
4327 if (Parser.getTok().is(AsmToken::Exclaim)) {
4328 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4329 Parser.Lex(); // Eat the '!'.
4330 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004331
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004332 return false;
4333}
4334
Jim Grosbach7ce05792011-08-03 23:50:40 +00004335/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004336/// ( lsl | lsr | asr | ror ) , # shift_amount
4337/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00004338/// return true if it parses a shift otherwise it returns false.
4339bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
4340 unsigned &Amount) {
4341 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00004342 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004343 if (Tok.isNot(AsmToken::Identifier))
4344 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00004345 StringRef ShiftName = Tok.getString();
Jim Grosbachaf4edea2011-12-07 23:40:58 +00004346 if (ShiftName == "lsl" || ShiftName == "LSL" ||
4347 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson00828302011-03-18 22:50:18 +00004348 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004349 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00004350 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004351 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00004352 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004353 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00004354 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004355 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00004356 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004357 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00004358 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00004359 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004360
Jim Grosbach7ce05792011-08-03 23:50:40 +00004361 // rrx stands alone.
4362 Amount = 0;
4363 if (St != ARM_AM::rrx) {
4364 Loc = Parser.getTok().getLoc();
4365 // A '#' and a shift amount.
4366 const AsmToken &HashTok = Parser.getTok();
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004367 if (HashTok.isNot(AsmToken::Hash) &&
4368 HashTok.isNot(AsmToken::Dollar))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004369 return Error(HashTok.getLoc(), "'#' expected");
4370 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004371
Jim Grosbach7ce05792011-08-03 23:50:40 +00004372 const MCExpr *Expr;
4373 if (getParser().ParseExpression(Expr))
4374 return true;
4375 // Range check the immediate.
4376 // lsl, ror: 0 <= imm <= 31
4377 // lsr, asr: 0 <= imm <= 32
4378 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4379 if (!CE)
4380 return Error(Loc, "shift amount must be an immediate");
4381 int64_t Imm = CE->getValue();
4382 if (Imm < 0 ||
4383 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4384 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4385 return Error(Loc, "immediate shift value out of range");
4386 Amount = Imm;
4387 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004388
4389 return false;
4390}
4391
Jim Grosbach9d390362011-10-03 23:38:36 +00004392/// parseFPImm - A floating point immediate expression operand.
4393ARMAsmParser::OperandMatchResultTy ARMAsmParser::
4394parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach51222d12012-01-20 18:09:51 +00004395 // Anything that can accept a floating point constant as an operand
4396 // needs to go through here, as the regular ParseExpression is
4397 // integer only.
4398 //
4399 // This routine still creates a generic Immediate operand, containing
4400 // a bitcast of the 64-bit floating point value. The various operands
4401 // that accept floats can check whether the value is valid for them
4402 // via the standard is*() predicates.
4403
Jim Grosbach9d390362011-10-03 23:38:36 +00004404 SMLoc S = Parser.getTok().getLoc();
4405
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004406 if (Parser.getTok().isNot(AsmToken::Hash) &&
4407 Parser.getTok().isNot(AsmToken::Dollar))
Jim Grosbach9d390362011-10-03 23:38:36 +00004408 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00004409
4410 // Disambiguate the VMOV forms that can accept an FP immediate.
4411 // vmov.f32 <sreg>, #imm
4412 // vmov.f64 <dreg>, #imm
4413 // vmov.f32 <dreg>, #imm @ vector f32x2
4414 // vmov.f32 <qreg>, #imm @ vector f32x4
4415 //
4416 // There are also the NEON VMOV instructions which expect an
4417 // integer constant. Make sure we don't try to parse an FPImm
4418 // for these:
4419 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4420 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4421 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4422 TyOp->getToken() != ".f64"))
4423 return MatchOperand_NoMatch;
4424
Jim Grosbach9d390362011-10-03 23:38:36 +00004425 Parser.Lex(); // Eat the '#'.
4426
4427 // Handle negation, as that still comes through as a separate token.
4428 bool isNegative = false;
4429 if (Parser.getTok().is(AsmToken::Minus)) {
4430 isNegative = true;
4431 Parser.Lex();
4432 }
4433 const AsmToken &Tok = Parser.getTok();
Jim Grosbachae69f702012-01-19 02:47:30 +00004434 SMLoc Loc = Tok.getLoc();
Jim Grosbach9d390362011-10-03 23:38:36 +00004435 if (Tok.is(AsmToken::Real)) {
Jim Grosbach51222d12012-01-20 18:09:51 +00004436 APFloat RealVal(APFloat::IEEEsingle, Tok.getString());
Jim Grosbach9d390362011-10-03 23:38:36 +00004437 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4438 // If we had a '-' in front, toggle the sign bit.
Jim Grosbach51222d12012-01-20 18:09:51 +00004439 IntVal ^= (uint64_t)isNegative << 31;
Jim Grosbach9d390362011-10-03 23:38:36 +00004440 Parser.Lex(); // Eat the token.
Jim Grosbach51222d12012-01-20 18:09:51 +00004441 Operands.push_back(ARMOperand::CreateImm(
4442 MCConstantExpr::Create(IntVal, getContext()),
4443 S, Parser.getTok().getLoc()));
Jim Grosbach9d390362011-10-03 23:38:36 +00004444 return MatchOperand_Success;
4445 }
Jim Grosbach51222d12012-01-20 18:09:51 +00004446 // Also handle plain integers. Instructions which allow floating point
4447 // immediates also allow a raw encoded 8-bit value.
Jim Grosbach9d390362011-10-03 23:38:36 +00004448 if (Tok.is(AsmToken::Integer)) {
4449 int64_t Val = Tok.getIntVal();
4450 Parser.Lex(); // Eat the token.
4451 if (Val > 255 || Val < 0) {
Jim Grosbachae69f702012-01-19 02:47:30 +00004452 Error(Loc, "encoded floating point value out of range");
Jim Grosbach9d390362011-10-03 23:38:36 +00004453 return MatchOperand_ParseFail;
4454 }
Jim Grosbach51222d12012-01-20 18:09:51 +00004455 double RealVal = ARM_AM::getFPImmFloat(Val);
4456 Val = APFloat(APFloat::IEEEdouble, RealVal).bitcastToAPInt().getZExtValue();
4457 Operands.push_back(ARMOperand::CreateImm(
4458 MCConstantExpr::Create(Val, getContext()), S,
4459 Parser.getTok().getLoc()));
Jim Grosbach9d390362011-10-03 23:38:36 +00004460 return MatchOperand_Success;
4461 }
4462
Jim Grosbachae69f702012-01-19 02:47:30 +00004463 Error(Loc, "invalid floating point immediate");
Jim Grosbach9d390362011-10-03 23:38:36 +00004464 return MatchOperand_ParseFail;
4465}
Jim Grosbach51222d12012-01-20 18:09:51 +00004466
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004467/// Parse a arm instruction operand. For now this parses the operand regardless
4468/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004469bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004470 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00004471 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004472
4473 // Check if the current operand has a custom associated parser, if so, try to
4474 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00004475 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4476 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004477 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00004478 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4479 // there was a match, but an error occurred, in which case, just return that
4480 // the operand parsing failed.
4481 if (ResTy == MatchOperand_ParseFail)
4482 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004483
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004484 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00004485 default:
4486 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00004487 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00004488 case AsmToken::Identifier: {
Jim Grosbach1355cf12011-07-26 17:10:22 +00004489 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00004490 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00004491 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00004492 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00004493 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00004494 else if (Res == -1) // irrecoverable error
4495 return true;
Jim Grosbach3cbe43f2011-12-20 22:26:38 +00004496 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbachb84ad4a2012-03-15 21:34:14 +00004497 if (Mnemonic == "vmrs" &&
4498 Parser.getTok().getString().equals_lower("apsr_nzcv")) {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004499 S = Parser.getTok().getLoc();
4500 Parser.Lex();
Jim Grosbachb84ad4a2012-03-15 21:34:14 +00004501 Operands.push_back(ARMOperand::CreateToken("APSR_nzcv", S));
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004502 return false;
4503 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00004504
4505 // Fall though for the Identifier case that is not a register or a
4506 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00004507 }
Jim Grosbach758a5192011-10-26 21:14:08 +00004508 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00004509 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00004510 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00004511 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00004512 // This was not a register so parse other operands that start with an
4513 // identifier (like labels) as expressions and create them as immediates.
4514 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00004515 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00004516 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004517 return true;
Sean Callanan76264762010-04-02 22:27:05 +00004518 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004519 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4520 return false;
4521 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004522 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004523 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00004524 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004525 return parseRegisterList(Operands);
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004526 case AsmToken::Dollar:
Owen Anderson63553c72011-08-29 17:17:09 +00004527 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00004528 // #42 -> immediate.
Sean Callanan76264762010-04-02 22:27:05 +00004529 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004530 Parser.Lex();
Jim Grosbachb8768dc2012-04-16 21:18:46 +00004531
4532 if (Parser.getTok().isNot(AsmToken::Colon)) {
4533 bool isNegative = Parser.getTok().is(AsmToken::Minus);
4534 const MCExpr *ImmVal;
4535 if (getParser().ParseExpression(ImmVal))
4536 return true;
4537 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
4538 if (CE) {
4539 int32_t Val = CE->getValue();
4540 if (isNegative && Val == 0)
4541 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
4542 }
4543 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4544 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4545 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00004546 }
Jim Grosbachb8768dc2012-04-16 21:18:46 +00004547 // w/ a ':' after the '#', it's just like a plain ':'.
4548 // FALLTHROUGH
Owen Anderson63553c72011-08-29 17:17:09 +00004549 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004550 case AsmToken::Colon: {
4551 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00004552 // FIXME: Check it's an expression prefix,
4553 // e.g. (FOO - :lower16:BAR) isn't legal.
4554 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004555 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004556 return true;
4557
Evan Cheng75972122011-01-13 07:58:56 +00004558 const MCExpr *SubExprVal;
4559 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004560 return true;
4561
Evan Cheng75972122011-01-13 07:58:56 +00004562 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4563 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00004564 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00004565 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00004566 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004567 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004568 }
4569}
4570
Jim Grosbach1355cf12011-07-26 17:10:22 +00004571// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00004572// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004573bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00004574 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004575
4576 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00004577 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00004578 Parser.Lex(); // Eat ':'
4579
4580 if (getLexer().isNot(AsmToken::Identifier)) {
4581 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4582 return true;
4583 }
4584
4585 StringRef IDVal = Parser.getTok().getIdentifier();
4586 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00004587 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004588 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00004589 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004590 } else {
4591 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4592 return true;
4593 }
4594 Parser.Lex();
4595
4596 if (getLexer().isNot(AsmToken::Colon)) {
4597 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4598 return true;
4599 }
4600 Parser.Lex(); // Eat the last ':'
4601 return false;
4602}
4603
Daniel Dunbar352e1482011-01-11 15:59:50 +00004604/// \brief Given a mnemonic, split out possible predication code and carry
4605/// setting letters to form a canonical mnemonic and flags.
4606//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004607// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00004608// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004609StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00004610 unsigned &PredicationCode,
4611 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004612 unsigned &ProcessorIMod,
4613 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004614 PredicationCode = ARMCC::AL;
4615 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004616 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004617
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004618 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00004619 //
4620 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00004621 if ((Mnemonic == "movs" && isThumb()) ||
4622 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4623 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4624 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4625 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4626 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4627 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
Jim Grosbach68490192011-12-19 19:43:50 +00004628 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" ||
4629 Mnemonic == "fmuls")
Daniel Dunbar352e1482011-01-11 15:59:50 +00004630 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00004631
Jim Grosbach3f00e312011-07-11 17:09:57 +00004632 // First, split out any predication code. Ignore mnemonics we know aren't
4633 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00004634 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00004635 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00004636 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00004637 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00004638 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4639 .Case("eq", ARMCC::EQ)
4640 .Case("ne", ARMCC::NE)
4641 .Case("hs", ARMCC::HS)
4642 .Case("cs", ARMCC::HS)
4643 .Case("lo", ARMCC::LO)
4644 .Case("cc", ARMCC::LO)
4645 .Case("mi", ARMCC::MI)
4646 .Case("pl", ARMCC::PL)
4647 .Case("vs", ARMCC::VS)
4648 .Case("vc", ARMCC::VC)
4649 .Case("hi", ARMCC::HI)
4650 .Case("ls", ARMCC::LS)
4651 .Case("ge", ARMCC::GE)
4652 .Case("lt", ARMCC::LT)
4653 .Case("gt", ARMCC::GT)
4654 .Case("le", ARMCC::LE)
4655 .Case("al", ARMCC::AL)
4656 .Default(~0U);
4657 if (CC != ~0U) {
4658 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4659 PredicationCode = CC;
4660 }
Bill Wendling52925b62010-10-29 23:50:21 +00004661 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004662
Daniel Dunbar352e1482011-01-11 15:59:50 +00004663 // Next, determine if we have a carry setting bit. We explicitly ignore all
4664 // the instructions we know end in 's'.
4665 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00004666 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00004667 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4668 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4669 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach67ca1ad2011-12-08 00:49:29 +00004670 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach48171e72011-12-10 00:01:02 +00004671 Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
Jim Grosbach9c397892011-12-19 19:02:41 +00004672 Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" ||
Jim Grosbach6357cae2012-03-15 20:48:18 +00004673 Mnemonic == "fmuls" || Mnemonic == "fcmps" || Mnemonic == "fcmpzs" ||
Evan Cheng82509e52012-04-11 00:13:00 +00004674 Mnemonic == "vfms" || Mnemonic == "vfnms" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00004675 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004676 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4677 CarrySetting = true;
4678 }
4679
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004680 // The "cps" instruction can have a interrupt mode operand which is glued into
4681 // the mnemonic. Check if this is the case, split it and parse the imod op
4682 if (Mnemonic.startswith("cps")) {
4683 // Split out any imod code.
4684 unsigned IMod =
4685 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4686 .Case("ie", ARM_PROC::IE)
4687 .Case("id", ARM_PROC::ID)
4688 .Default(~0U);
4689 if (IMod != ~0U) {
4690 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4691 ProcessorIMod = IMod;
4692 }
4693 }
4694
Jim Grosbach89df9962011-08-26 21:43:41 +00004695 // The "it" instruction has the condition mask on the end of the mnemonic.
4696 if (Mnemonic.startswith("it")) {
4697 ITMask = Mnemonic.slice(2, Mnemonic.size());
4698 Mnemonic = Mnemonic.slice(0, 2);
4699 }
4700
Daniel Dunbar352e1482011-01-11 15:59:50 +00004701 return Mnemonic;
4702}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004703
4704/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4705/// inclusion of carry set or predication code operands.
4706//
4707// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004708void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00004709getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004710 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004711 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4712 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004713 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004714 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004715 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004716 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004717 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Evan Cheng82509e52012-04-11 00:13:00 +00004718 Mnemonic == "vfm" || Mnemonic == "vfnm" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004719 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004720 Mnemonic == "mla" || Mnemonic == "smlal" ||
4721 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004722 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004723 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004724 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004725
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004726 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4727 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4728 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4729 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004730 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4731 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004732 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004733 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4734 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4735 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004736 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4737 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004738 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004739 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004740 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004741 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004742
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004743 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004744 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004745 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004746 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004747 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004748}
4749
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004750bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4751 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004752 // FIXME: This is all horribly hacky. We really need a better way to deal
4753 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004754
4755 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4756 // another does not. Specifically, the MOVW instruction does not. So we
4757 // special case it here and remove the defaulted (non-setting) cc_out
4758 // operand if that's the instruction we're trying to match.
4759 //
4760 // We do this as post-processing of the explicit operands rather than just
4761 // conditionally adding the cc_out in the first place because we need
4762 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004763 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004764 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4765 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4766 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4767 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004768
4769 // Register-register 'add' for thumb does not have a cc_out operand
4770 // when there are only two register operands.
4771 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4772 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4773 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4774 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4775 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004776 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004777 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4778 // have to check the immediate range here since Thumb2 has a variant
4779 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004780 if (((isThumb() && Mnemonic == "add") ||
4781 (isThumbTwo() && Mnemonic == "sub")) &&
4782 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004783 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4784 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4785 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004786 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
Jim Grosbacha23ecc22012-04-10 17:31:55 +00004787 ((Mnemonic == "add" &&static_cast<ARMOperand*>(Operands[5])->isReg()) ||
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004788 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004789 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004790 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4791 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004792 // selecting via the generic "add" mnemonic, so to know that we
4793 // should remove the cc_out operand, we have to explicitly check that
4794 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004795 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4796 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004797 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4798 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4799 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4800 // Nest conditions rather than one big 'if' statement for readability.
4801 //
4802 // If either register is a high reg, it's either one of the SP
4803 // variants (handled above) or a 32-bit encoding, so we just
Jim Grosbach12a88632012-01-21 00:07:56 +00004804 // check against T3. If the second register is the PC, this is an
4805 // alternate form of ADR, which uses encoding T4, so check for that too.
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004806 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4807 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
Jim Grosbach12a88632012-01-21 00:07:56 +00004808 static_cast<ARMOperand*>(Operands[4])->getReg() != ARM::PC &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004809 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4810 return false;
4811 // If both registers are low, we're in an IT block, and the immediate is
4812 // in range, we should use encoding T1 instead, which has a cc_out.
4813 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004814 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004815 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4816 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4817 return false;
4818
4819 // Otherwise, we use encoding T4, which does not have a cc_out
4820 // operand.
4821 return true;
4822 }
4823
Jim Grosbach64944f42011-09-14 21:00:40 +00004824 // The thumb2 multiply instruction doesn't have a CCOut register, so
4825 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4826 // use the 16-bit encoding or not.
4827 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4828 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4829 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4830 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4831 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4832 // If the registers aren't low regs, the destination reg isn't the
4833 // same as one of the source regs, or the cc_out operand is zero
4834 // outside of an IT block, we have to use the 32-bit encoding, so
4835 // remove the cc_out operand.
4836 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4837 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach1de0bd12011-11-15 19:29:45 +00004838 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach64944f42011-09-14 21:00:40 +00004839 !inITBlock() ||
4840 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4841 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4842 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4843 static_cast<ARMOperand*>(Operands[4])->getReg())))
4844 return true;
4845
Jim Grosbach7f1ec952011-11-15 19:55:16 +00004846 // Also check the 'mul' syntax variant that doesn't specify an explicit
4847 // destination register.
4848 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4849 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4850 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4851 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4852 // If the registers aren't low regs or the cc_out operand is zero
4853 // outside of an IT block, we have to use the 32-bit encoding, so
4854 // remove the cc_out operand.
4855 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4856 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4857 !inITBlock()))
4858 return true;
4859
Jim Grosbach64944f42011-09-14 21:00:40 +00004860
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004861
Jim Grosbachf69c8042011-08-24 21:42:27 +00004862 // Register-register 'add/sub' for thumb does not have a cc_out operand
4863 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4864 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4865 // right, this will result in better diagnostics (which operand is off)
4866 // anyway.
4867 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4868 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004869 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4870 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
Jim Grosbacha23ecc22012-04-10 17:31:55 +00004871 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4872 (static_cast<ARMOperand*>(Operands[4])->isImm() ||
4873 (Operands.size() == 6 &&
4874 static_cast<ARMOperand*>(Operands[5])->isImm())))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004875 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004876
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004877 return false;
4878}
4879
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004880static bool isDataTypeToken(StringRef Tok) {
4881 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4882 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4883 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4884 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4885 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4886 Tok == ".f" || Tok == ".d";
4887}
4888
4889// FIXME: This bit should probably be handled via an explicit match class
4890// in the .td files that matches the suffix instead of having it be
4891// a literal string token the way it is now.
4892static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4893 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4894}
4895
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004896static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004897/// Parse an arm instruction mnemonic followed by its operands.
4898bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4899 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004900 // Apply mnemonic aliases before doing anything else, as the destination
4901 // mnemnonic may include suffices and we want to handle them normally.
4902 // The generic tblgen'erated code does this later, at the start of
4903 // MatchInstructionImpl(), but that's too late for aliases that include
4904 // any sort of suffix.
4905 unsigned AvailableFeatures = getAvailableFeatures();
4906 applyMnemonicAliases(Name, AvailableFeatures);
4907
Jim Grosbacha39cda72011-12-14 02:16:11 +00004908 // First check for the ARM-specific .req directive.
4909 if (Parser.getTok().is(AsmToken::Identifier) &&
4910 Parser.getTok().getIdentifier() == ".req") {
4911 parseDirectiveReq(Name, NameLoc);
4912 // We always return 'error' for this, as we're done with this
4913 // statement and don't need to match the 'instruction."
4914 return true;
4915 }
4916
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004917 // Create the leading tokens for the mnemonic, split by '.' characters.
4918 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004919 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004920
Daniel Dunbar352e1482011-01-11 15:59:50 +00004921 // Split out the predication code and carry setting flag from the mnemonic.
4922 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004923 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004924 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004925 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004926 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004927 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004928
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004929 // In Thumb1, only the branch (B) instruction can be predicated.
4930 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4931 Parser.EatToEndOfStatement();
4932 return Error(NameLoc, "conditional execution not supported in Thumb1");
4933 }
4934
Jim Grosbachffa32252011-07-19 19:13:28 +00004935 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4936
Jim Grosbach89df9962011-08-26 21:43:41 +00004937 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4938 // is the mask as it will be for the IT encoding if the conditional
4939 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4940 // where the conditional bit0 is zero, the instruction post-processing
4941 // will adjust the mask accordingly.
4942 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004943 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4944 if (ITMask.size() > 3) {
4945 Parser.EatToEndOfStatement();
4946 return Error(Loc, "too many conditions on IT instruction");
4947 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004948 unsigned Mask = 8;
4949 for (unsigned i = ITMask.size(); i != 0; --i) {
4950 char pos = ITMask[i - 1];
4951 if (pos != 't' && pos != 'e') {
4952 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004953 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004954 }
4955 Mask >>= 1;
4956 if (ITMask[i - 1] == 't')
4957 Mask |= 8;
4958 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004959 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004960 }
4961
Jim Grosbachffa32252011-07-19 19:13:28 +00004962 // FIXME: This is all a pretty gross hack. We should automatically handle
4963 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004964
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004965 // Next, add the CCOut and ConditionCode operands, if needed.
4966 //
4967 // For mnemonics which can ever incorporate a carry setting bit or predication
4968 // code, our matching model involves us always generating CCOut and
4969 // ConditionCode operands to match the mnemonic "as written" and then we let
4970 // the matcher deal with finding the right instruction or generating an
4971 // appropriate error.
4972 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004973 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004974
Jim Grosbach33c16a22011-07-14 22:04:21 +00004975 // If we had a carry-set on an instruction that can't do that, issue an
4976 // error.
4977 if (!CanAcceptCarrySet && CarrySetting) {
4978 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004979 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004980 "' can not set flags, but 's' suffix specified");
4981 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004982 // If we had a predication code on an instruction that can't do that, issue an
4983 // error.
4984 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4985 Parser.EatToEndOfStatement();
4986 return Error(NameLoc, "instruction '" + Mnemonic +
4987 "' is not predicable, but condition code specified");
4988 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004989
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004990 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004991 if (CanAcceptCarrySet) {
4992 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004993 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004994 Loc));
4995 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004996
4997 // Add the predication code operand, if necessary.
4998 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004999 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
5000 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00005001 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005002 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00005003 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00005004
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00005005 // Add the processor imod operand, if necessary.
5006 if (ProcessorIMod) {
5007 Operands.push_back(ARMOperand::CreateImm(
5008 MCConstantExpr::Create(ProcessorIMod, getContext()),
5009 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00005010 }
5011
Daniel Dunbar345a9a62010-08-11 06:37:20 +00005012 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00005013 while (Next != StringRef::npos) {
5014 Start = Next;
5015 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00005016 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00005017
Jim Grosbach7aef99b2011-11-11 23:08:10 +00005018 // Some NEON instructions have an optional datatype suffix that is
5019 // completely ignored. Check for that.
5020 if (isDataTypeToken(ExtraToken) &&
5021 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
5022 continue;
5023
Jim Grosbach81d2e392011-09-07 16:06:04 +00005024 if (ExtraToken != ".n") {
5025 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
5026 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
5027 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00005028 }
5029
5030 // Read the remaining operands.
5031 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00005032 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00005033 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00005034 Parser.EatToEndOfStatement();
5035 return true;
5036 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00005037
5038 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00005039 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00005040
5041 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00005042 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00005043 Parser.EatToEndOfStatement();
5044 return true;
5045 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00005046 }
5047 }
Jim Grosbach16c74252010-10-29 14:46:02 +00005048
Chris Lattnercbf8a982010-09-11 16:18:25 +00005049 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00005050 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00005051 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00005052 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00005053 }
Bill Wendling146018f2010-11-06 21:42:12 +00005054
Chris Lattner34e53142010-09-08 05:10:46 +00005055 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00005056
Jim Grosbachd54b4e62011-08-16 21:12:37 +00005057 // Some instructions, mostly Thumb, have forms for the same mnemonic that
5058 // do and don't have a cc_out optional-def operand. With some spot-checks
5059 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00005060 // parse and adjust accordingly before actually matching. We shouldn't ever
5061 // try to remove a cc_out operand that was explicitly set on the the
5062 // mnemonic, of course (CarrySetting == true). Reason number #317 the
5063 // table driven matcher doesn't fit well with the ARM instruction set.
5064 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00005065 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
5066 Operands.erase(Operands.begin() + 1);
5067 delete Op;
5068 }
5069
Jim Grosbachcf121c32011-07-28 21:57:55 +00005070 // ARM mode 'blx' need special handling, as the register operand version
5071 // is predicable, but the label operand version is not. So, we can't rely
5072 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00005073 // a k_CondCode operand in the list. If we're trying to match the label
5074 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00005075 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
5076 static_cast<ARMOperand*>(Operands[2])->isImm()) {
5077 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
5078 Operands.erase(Operands.begin() + 1);
5079 delete Op;
5080 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00005081
5082 // The vector-compare-to-zero instructions have a literal token "#0" at
5083 // the end that comes to here as an immediate operand. Convert it to a
5084 // token to play nicely with the matcher.
5085 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
5086 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
5087 static_cast<ARMOperand*>(Operands[5])->isImm()) {
5088 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
5089 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
5090 if (CE && CE->getValue() == 0) {
5091 Operands.erase(Operands.begin() + 5);
5092 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5093 delete Op;
5094 }
5095 }
Jim Grosbach68259142011-10-03 22:30:24 +00005096 // VCMP{E} does the same thing, but with a different operand count.
5097 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
5098 static_cast<ARMOperand*>(Operands[4])->isImm()) {
5099 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
5100 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
5101 if (CE && CE->getValue() == 0) {
5102 Operands.erase(Operands.begin() + 4);
5103 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5104 delete Op;
5105 }
5106 }
Jim Grosbach934755a2011-08-22 23:47:13 +00005107 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
Jim Grosbach55b02f22011-12-13 20:50:38 +00005108 // end. Convert it to a token here. Take care not to convert those
5109 // that should hit the Thumb2 encoding.
Jim Grosbach934755a2011-08-22 23:47:13 +00005110 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
Jim Grosbach55b02f22011-12-13 20:50:38 +00005111 static_cast<ARMOperand*>(Operands[3])->isReg() &&
5112 static_cast<ARMOperand*>(Operands[4])->isReg() &&
Jim Grosbach934755a2011-08-22 23:47:13 +00005113 static_cast<ARMOperand*>(Operands[5])->isImm()) {
5114 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
5115 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
Jim Grosbach55b02f22011-12-13 20:50:38 +00005116 if (CE && CE->getValue() == 0 &&
5117 (isThumbOne() ||
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00005118 // The cc_out operand matches the IT block.
5119 ((inITBlock() != CarrySetting) &&
5120 // Neither register operand is a high register.
Jim Grosbach55b02f22011-12-13 20:50:38 +00005121 (isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00005122 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()))))){
Jim Grosbach934755a2011-08-22 23:47:13 +00005123 Operands.erase(Operands.begin() + 5);
5124 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5125 delete Op;
5126 }
5127 }
5128
Chris Lattner98986712010-01-14 22:21:20 +00005129 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005130}
5131
Jim Grosbach189610f2011-07-26 18:25:39 +00005132// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00005133
5134// return 'true' if register list contains non-low GPR registers,
5135// 'false' otherwise. If Reg is in the register list or is HiReg, set
5136// 'containsReg' to true.
5137static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
5138 unsigned HiReg, bool &containsReg) {
5139 containsReg = false;
5140 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5141 unsigned OpReg = Inst.getOperand(i).getReg();
5142 if (OpReg == Reg)
5143 containsReg = true;
5144 // Anything other than a low register isn't legal here.
5145 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
5146 return true;
5147 }
5148 return false;
5149}
5150
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005151// Check if the specified regisgter is in the register list of the inst,
5152// starting at the indicated operand number.
5153static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
5154 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5155 unsigned OpReg = Inst.getOperand(i).getReg();
5156 if (OpReg == Reg)
5157 return true;
5158 }
5159 return false;
5160}
5161
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005162// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
5163// the ARMInsts array) instead. Getting that here requires awkward
5164// API changes, though. Better way?
5165namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005166extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005167}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005168static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005169 return ARMInsts[Opcode];
5170}
5171
Jim Grosbach189610f2011-07-26 18:25:39 +00005172// FIXME: We would really like to be able to tablegen'erate this.
5173bool ARMAsmParser::
5174validateInstruction(MCInst &Inst,
5175 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005176 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005177 SMLoc Loc = Operands[0]->getStartLoc();
5178 // Check the IT block state first.
Jim Grosbach74423e32012-01-25 19:52:01 +00005179 // NOTE: BKPT instruction has the interesting property of being
5180 // allowed in IT blocks, but not being predicable. It just always
Owen Andersonb6b7f512011-09-13 17:59:19 +00005181 // executes.
Jim Grosbach74423e32012-01-25 19:52:01 +00005182 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT &&
5183 Inst.getOpcode() != ARM::BKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005184 unsigned bit = 1;
5185 if (ITState.FirstCond)
5186 ITState.FirstCond = false;
5187 else
Jim Grosbacha1109882011-09-02 23:22:08 +00005188 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005189 // The instruction must be predicable.
5190 if (!MCID.isPredicable())
5191 return Error(Loc, "instructions in IT block must be predicable");
5192 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
5193 unsigned ITCond = bit ? ITState.Cond :
5194 ARMCC::getOppositeCondition(ITState.Cond);
5195 if (Cond != ITCond) {
5196 // Find the condition code Operand to get its SMLoc information.
5197 SMLoc CondLoc;
5198 for (unsigned i = 1; i < Operands.size(); ++i)
5199 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
5200 CondLoc = Operands[i]->getStartLoc();
5201 return Error(CondLoc, "incorrect condition in IT block; got '" +
5202 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
5203 "', but expected '" +
5204 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
5205 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00005206 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005207 } else if (isThumbTwo() && MCID.isPredicable() &&
5208 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005209 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
5210 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005211 return Error(Loc, "predicated instructions must be in IT block");
5212
Jim Grosbach189610f2011-07-26 18:25:39 +00005213 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00005214 case ARM::LDRD:
5215 case ARM::LDRD_PRE:
5216 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005217 case ARM::LDREXD: {
5218 // Rt2 must be Rt + 1.
5219 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5220 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5221 if (Rt2 != Rt + 1)
5222 return Error(Operands[3]->getStartLoc(),
5223 "destination operands must be sequential");
5224 return false;
5225 }
Jim Grosbach14605d12011-08-11 20:28:23 +00005226 case ARM::STRD: {
5227 // Rt2 must be Rt + 1.
5228 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5229 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5230 if (Rt2 != Rt + 1)
5231 return Error(Operands[3]->getStartLoc(),
5232 "source operands must be sequential");
5233 return false;
5234 }
Jim Grosbach53642c52011-08-10 20:49:18 +00005235 case ARM::STRD_PRE:
5236 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005237 case ARM::STREXD: {
5238 // Rt2 must be Rt + 1.
5239 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5240 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
5241 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00005242 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00005243 "source operands must be sequential");
5244 return false;
5245 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005246 case ARM::SBFX:
5247 case ARM::UBFX: {
5248 // width must be in range [1, 32-lsb]
5249 unsigned lsb = Inst.getOperand(2).getImm();
5250 unsigned widthm1 = Inst.getOperand(3).getImm();
5251 if (widthm1 >= 32 - lsb)
5252 return Error(Operands[5]->getStartLoc(),
5253 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00005254 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005255 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005256 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005257 // If we're parsing Thumb2, the .w variant is available and handles
5258 // most cases that are normally illegal for a Thumb1 LDM
5259 // instruction. We'll make the transformation in processInstruction()
5260 // if necessary.
5261 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005262 // Thumb LDM instructions are writeback iff the base register is not
5263 // in the register list.
5264 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005265 bool hasWritebackToken =
5266 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5267 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00005268 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005269 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005270 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
5271 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005272 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005273 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005274 return Error(Operands[2]->getStartLoc(),
5275 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005276 // If we should not have writeback, there must not be a '!'. This is
5277 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00005278 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005279 return Error(Operands[3]->getStartLoc(),
5280 "writeback operator '!' not allowed when base register "
5281 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005282
5283 break;
5284 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005285 case ARM::t2LDMIA_UPD: {
5286 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
5287 return Error(Operands[4]->getStartLoc(),
5288 "writeback operator '!' not allowed when base register "
5289 "in register list");
5290 break;
5291 }
Jim Grosbach54026372011-11-10 23:17:11 +00005292 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
5293 // so only issue a diagnostic for thumb1. The instructions will be
5294 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005295 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005296 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005297 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
5298 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005299 return Error(Operands[2]->getStartLoc(),
5300 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005301 break;
5302 }
5303 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005304 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005305 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
5306 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005307 return Error(Operands[2]->getStartLoc(),
5308 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005309 break;
5310 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00005311 case ARM::tSTMIA_UPD: {
5312 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00005313 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00005314 return Error(Operands[4]->getStartLoc(),
5315 "registers must be in range r0-r7");
5316 break;
5317 }
Jim Grosbach189610f2011-07-26 18:25:39 +00005318 }
5319
5320 return false;
5321}
5322
Jim Grosbachd7433e22012-01-23 23:45:44 +00005323static unsigned getRealVSTOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach84defb52011-12-02 22:34:51 +00005324 switch(Opc) {
Craig Topperbc219812012-02-07 02:50:20 +00005325 default: llvm_unreachable("unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005326 // VST1LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005327 case ARM::VST1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
5328 case ARM::VST1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
5329 case ARM::VST1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
5330 case ARM::VST1LNdWB_register_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
5331 case ARM::VST1LNdWB_register_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
5332 case ARM::VST1LNdWB_register_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
5333 case ARM::VST1LNdAsm_8: Spacing = 1; return ARM::VST1LNd8;
5334 case ARM::VST1LNdAsm_16: Spacing = 1; return ARM::VST1LNd16;
5335 case ARM::VST1LNdAsm_32: Spacing = 1; return ARM::VST1LNd32;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005336
5337 // VST2LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005338 case ARM::VST2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
5339 case ARM::VST2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
5340 case ARM::VST2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
5341 case ARM::VST2LNqWB_fixed_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
5342 case ARM::VST2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005343
Jim Grosbach7945ead2012-01-24 00:43:12 +00005344 case ARM::VST2LNdWB_register_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
5345 case ARM::VST2LNdWB_register_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
5346 case ARM::VST2LNdWB_register_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
5347 case ARM::VST2LNqWB_register_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
5348 case ARM::VST2LNqWB_register_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005349
Jim Grosbach7945ead2012-01-24 00:43:12 +00005350 case ARM::VST2LNdAsm_8: Spacing = 1; return ARM::VST2LNd8;
5351 case ARM::VST2LNdAsm_16: Spacing = 1; return ARM::VST2LNd16;
5352 case ARM::VST2LNdAsm_32: Spacing = 1; return ARM::VST2LNd32;
5353 case ARM::VST2LNqAsm_16: Spacing = 2; return ARM::VST2LNq16;
5354 case ARM::VST2LNqAsm_32: Spacing = 2; return ARM::VST2LNq32;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005355
Jim Grosbach4adb1822012-01-24 00:07:41 +00005356 // VST3LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005357 case ARM::VST3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
5358 case ARM::VST3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
5359 case ARM::VST3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
5360 case ARM::VST3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNq16_UPD;
5361 case ARM::VST3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
5362 case ARM::VST3LNdWB_register_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
5363 case ARM::VST3LNdWB_register_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
5364 case ARM::VST3LNdWB_register_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
5365 case ARM::VST3LNqWB_register_Asm_16: Spacing = 2; return ARM::VST3LNq16_UPD;
5366 case ARM::VST3LNqWB_register_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
5367 case ARM::VST3LNdAsm_8: Spacing = 1; return ARM::VST3LNd8;
5368 case ARM::VST3LNdAsm_16: Spacing = 1; return ARM::VST3LNd16;
5369 case ARM::VST3LNdAsm_32: Spacing = 1; return ARM::VST3LNd32;
5370 case ARM::VST3LNqAsm_16: Spacing = 2; return ARM::VST3LNq16;
5371 case ARM::VST3LNqAsm_32: Spacing = 2; return ARM::VST3LNq32;
Jim Grosbach4adb1822012-01-24 00:07:41 +00005372
Jim Grosbachd7433e22012-01-23 23:45:44 +00005373 // VST3
Jim Grosbach7945ead2012-01-24 00:43:12 +00005374 case ARM::VST3dWB_fixed_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
5375 case ARM::VST3dWB_fixed_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
5376 case ARM::VST3dWB_fixed_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
5377 case ARM::VST3qWB_fixed_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
5378 case ARM::VST3qWB_fixed_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
5379 case ARM::VST3qWB_fixed_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
5380 case ARM::VST3dWB_register_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
5381 case ARM::VST3dWB_register_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
5382 case ARM::VST3dWB_register_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
5383 case ARM::VST3qWB_register_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
5384 case ARM::VST3qWB_register_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
5385 case ARM::VST3qWB_register_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
5386 case ARM::VST3dAsm_8: Spacing = 1; return ARM::VST3d8;
5387 case ARM::VST3dAsm_16: Spacing = 1; return ARM::VST3d16;
5388 case ARM::VST3dAsm_32: Spacing = 1; return ARM::VST3d32;
5389 case ARM::VST3qAsm_8: Spacing = 2; return ARM::VST3q8;
5390 case ARM::VST3qAsm_16: Spacing = 2; return ARM::VST3q16;
5391 case ARM::VST3qAsm_32: Spacing = 2; return ARM::VST3q32;
Jim Grosbach539aab72012-01-24 00:58:13 +00005392
Jim Grosbach88a54de2012-01-24 18:53:13 +00005393 // VST4LN
5394 case ARM::VST4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD;
5395 case ARM::VST4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD;
5396 case ARM::VST4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD;
5397 case ARM::VST4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNq16_UPD;
5398 case ARM::VST4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD;
5399 case ARM::VST4LNdWB_register_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD;
5400 case ARM::VST4LNdWB_register_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD;
5401 case ARM::VST4LNdWB_register_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD;
5402 case ARM::VST4LNqWB_register_Asm_16: Spacing = 2; return ARM::VST4LNq16_UPD;
5403 case ARM::VST4LNqWB_register_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD;
5404 case ARM::VST4LNdAsm_8: Spacing = 1; return ARM::VST4LNd8;
5405 case ARM::VST4LNdAsm_16: Spacing = 1; return ARM::VST4LNd16;
5406 case ARM::VST4LNdAsm_32: Spacing = 1; return ARM::VST4LNd32;
5407 case ARM::VST4LNqAsm_16: Spacing = 2; return ARM::VST4LNq16;
5408 case ARM::VST4LNqAsm_32: Spacing = 2; return ARM::VST4LNq32;
5409
Jim Grosbach539aab72012-01-24 00:58:13 +00005410 // VST4
5411 case ARM::VST4dWB_fixed_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
5412 case ARM::VST4dWB_fixed_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
5413 case ARM::VST4dWB_fixed_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
5414 case ARM::VST4qWB_fixed_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
5415 case ARM::VST4qWB_fixed_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
5416 case ARM::VST4qWB_fixed_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
5417 case ARM::VST4dWB_register_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
5418 case ARM::VST4dWB_register_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
5419 case ARM::VST4dWB_register_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
5420 case ARM::VST4qWB_register_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
5421 case ARM::VST4qWB_register_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
5422 case ARM::VST4qWB_register_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
5423 case ARM::VST4dAsm_8: Spacing = 1; return ARM::VST4d8;
5424 case ARM::VST4dAsm_16: Spacing = 1; return ARM::VST4d16;
5425 case ARM::VST4dAsm_32: Spacing = 1; return ARM::VST4d32;
5426 case ARM::VST4qAsm_8: Spacing = 2; return ARM::VST4q8;
5427 case ARM::VST4qAsm_16: Spacing = 2; return ARM::VST4q16;
5428 case ARM::VST4qAsm_32: Spacing = 2; return ARM::VST4q32;
Jim Grosbach84defb52011-12-02 22:34:51 +00005429 }
5430}
5431
Jim Grosbachd7433e22012-01-23 23:45:44 +00005432static unsigned getRealVLDOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005433 switch(Opc) {
Craig Topperbc219812012-02-07 02:50:20 +00005434 default: llvm_unreachable("unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005435 // VLD1LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005436 case ARM::VLD1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
5437 case ARM::VLD1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
5438 case ARM::VLD1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
5439 case ARM::VLD1LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
5440 case ARM::VLD1LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
5441 case ARM::VLD1LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
5442 case ARM::VLD1LNdAsm_8: Spacing = 1; return ARM::VLD1LNd8;
5443 case ARM::VLD1LNdAsm_16: Spacing = 1; return ARM::VLD1LNd16;
5444 case ARM::VLD1LNdAsm_32: Spacing = 1; return ARM::VLD1LNd32;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005445
5446 // VLD2LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005447 case ARM::VLD2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
5448 case ARM::VLD2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
5449 case ARM::VLD2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
5450 case ARM::VLD2LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNq16_UPD;
5451 case ARM::VLD2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
5452 case ARM::VLD2LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
5453 case ARM::VLD2LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
5454 case ARM::VLD2LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
5455 case ARM::VLD2LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD2LNq16_UPD;
5456 case ARM::VLD2LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
5457 case ARM::VLD2LNdAsm_8: Spacing = 1; return ARM::VLD2LNd8;
5458 case ARM::VLD2LNdAsm_16: Spacing = 1; return ARM::VLD2LNd16;
5459 case ARM::VLD2LNdAsm_32: Spacing = 1; return ARM::VLD2LNd32;
5460 case ARM::VLD2LNqAsm_16: Spacing = 2; return ARM::VLD2LNq16;
5461 case ARM::VLD2LNqAsm_32: Spacing = 2; return ARM::VLD2LNq32;
Jim Grosbach3a678af2012-01-23 21:53:26 +00005462
Jim Grosbach5e59f7e2012-01-24 23:47:04 +00005463 // VLD3DUP
5464 case ARM::VLD3DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD;
5465 case ARM::VLD3DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD;
5466 case ARM::VLD3DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD;
5467 case ARM::VLD3DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPq8_UPD;
5468 case ARM::VLD3DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPq16_UPD;
5469 case ARM::VLD3DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD;
5470 case ARM::VLD3DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD;
5471 case ARM::VLD3DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD;
5472 case ARM::VLD3DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD;
5473 case ARM::VLD3DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD3DUPq8_UPD;
5474 case ARM::VLD3DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD3DUPq16_UPD;
5475 case ARM::VLD3DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD;
5476 case ARM::VLD3DUPdAsm_8: Spacing = 1; return ARM::VLD3DUPd8;
5477 case ARM::VLD3DUPdAsm_16: Spacing = 1; return ARM::VLD3DUPd16;
5478 case ARM::VLD3DUPdAsm_32: Spacing = 1; return ARM::VLD3DUPd32;
5479 case ARM::VLD3DUPqAsm_8: Spacing = 2; return ARM::VLD3DUPq8;
5480 case ARM::VLD3DUPqAsm_16: Spacing = 2; return ARM::VLD3DUPq16;
5481 case ARM::VLD3DUPqAsm_32: Spacing = 2; return ARM::VLD3DUPq32;
5482
Jim Grosbach3a678af2012-01-23 21:53:26 +00005483 // VLD3LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005484 case ARM::VLD3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
5485 case ARM::VLD3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
5486 case ARM::VLD3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
5487 case ARM::VLD3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNq16_UPD;
5488 case ARM::VLD3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
5489 case ARM::VLD3LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
5490 case ARM::VLD3LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
5491 case ARM::VLD3LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
5492 case ARM::VLD3LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD3LNq16_UPD;
5493 case ARM::VLD3LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
5494 case ARM::VLD3LNdAsm_8: Spacing = 1; return ARM::VLD3LNd8;
5495 case ARM::VLD3LNdAsm_16: Spacing = 1; return ARM::VLD3LNd16;
5496 case ARM::VLD3LNdAsm_32: Spacing = 1; return ARM::VLD3LNd32;
5497 case ARM::VLD3LNqAsm_16: Spacing = 2; return ARM::VLD3LNq16;
5498 case ARM::VLD3LNqAsm_32: Spacing = 2; return ARM::VLD3LNq32;
Jim Grosbachc387fc62012-01-23 23:20:46 +00005499
5500 // VLD3
Jim Grosbach7945ead2012-01-24 00:43:12 +00005501 case ARM::VLD3dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
5502 case ARM::VLD3dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
5503 case ARM::VLD3dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
5504 case ARM::VLD3qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
5505 case ARM::VLD3qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
5506 case ARM::VLD3qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
5507 case ARM::VLD3dWB_register_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
5508 case ARM::VLD3dWB_register_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
5509 case ARM::VLD3dWB_register_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
5510 case ARM::VLD3qWB_register_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
5511 case ARM::VLD3qWB_register_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
5512 case ARM::VLD3qWB_register_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
5513 case ARM::VLD3dAsm_8: Spacing = 1; return ARM::VLD3d8;
5514 case ARM::VLD3dAsm_16: Spacing = 1; return ARM::VLD3d16;
5515 case ARM::VLD3dAsm_32: Spacing = 1; return ARM::VLD3d32;
5516 case ARM::VLD3qAsm_8: Spacing = 2; return ARM::VLD3q8;
5517 case ARM::VLD3qAsm_16: Spacing = 2; return ARM::VLD3q16;
5518 case ARM::VLD3qAsm_32: Spacing = 2; return ARM::VLD3q32;
Jim Grosbach8abe7e32012-01-24 00:43:17 +00005519
Jim Grosbache983a132012-01-24 18:37:25 +00005520 // VLD4LN
5521 case ARM::VLD4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD;
5522 case ARM::VLD4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
5523 case ARM::VLD4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
5524 case ARM::VLD4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNq16_UPD;
5525 case ARM::VLD4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
5526 case ARM::VLD4LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD;
5527 case ARM::VLD4LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
5528 case ARM::VLD4LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
5529 case ARM::VLD4LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD4LNq16_UPD;
5530 case ARM::VLD4LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
5531 case ARM::VLD4LNdAsm_8: Spacing = 1; return ARM::VLD4LNd8;
5532 case ARM::VLD4LNdAsm_16: Spacing = 1; return ARM::VLD4LNd16;
5533 case ARM::VLD4LNdAsm_32: Spacing = 1; return ARM::VLD4LNd32;
5534 case ARM::VLD4LNqAsm_16: Spacing = 2; return ARM::VLD4LNq16;
5535 case ARM::VLD4LNqAsm_32: Spacing = 2; return ARM::VLD4LNq32;
5536
Jim Grosbacha57a36a2012-01-25 00:01:08 +00005537 // VLD4DUP
5538 case ARM::VLD4DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD;
5539 case ARM::VLD4DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD;
5540 case ARM::VLD4DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD;
5541 case ARM::VLD4DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPq8_UPD;
5542 case ARM::VLD4DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPq16_UPD;
5543 case ARM::VLD4DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD;
5544 case ARM::VLD4DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD;
5545 case ARM::VLD4DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD;
5546 case ARM::VLD4DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD;
5547 case ARM::VLD4DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD4DUPq8_UPD;
5548 case ARM::VLD4DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD4DUPq16_UPD;
5549 case ARM::VLD4DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD;
5550 case ARM::VLD4DUPdAsm_8: Spacing = 1; return ARM::VLD4DUPd8;
5551 case ARM::VLD4DUPdAsm_16: Spacing = 1; return ARM::VLD4DUPd16;
5552 case ARM::VLD4DUPdAsm_32: Spacing = 1; return ARM::VLD4DUPd32;
5553 case ARM::VLD4DUPqAsm_8: Spacing = 2; return ARM::VLD4DUPq8;
5554 case ARM::VLD4DUPqAsm_16: Spacing = 2; return ARM::VLD4DUPq16;
5555 case ARM::VLD4DUPqAsm_32: Spacing = 2; return ARM::VLD4DUPq32;
5556
Jim Grosbach8abe7e32012-01-24 00:43:17 +00005557 // VLD4
5558 case ARM::VLD4dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
5559 case ARM::VLD4dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
5560 case ARM::VLD4dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
5561 case ARM::VLD4qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
5562 case ARM::VLD4qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
5563 case ARM::VLD4qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
5564 case ARM::VLD4dWB_register_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
5565 case ARM::VLD4dWB_register_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
5566 case ARM::VLD4dWB_register_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
5567 case ARM::VLD4qWB_register_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
5568 case ARM::VLD4qWB_register_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
5569 case ARM::VLD4qWB_register_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
5570 case ARM::VLD4dAsm_8: Spacing = 1; return ARM::VLD4d8;
5571 case ARM::VLD4dAsm_16: Spacing = 1; return ARM::VLD4d16;
5572 case ARM::VLD4dAsm_32: Spacing = 1; return ARM::VLD4d32;
5573 case ARM::VLD4qAsm_8: Spacing = 2; return ARM::VLD4q8;
5574 case ARM::VLD4qAsm_16: Spacing = 2; return ARM::VLD4q16;
5575 case ARM::VLD4qAsm_32: Spacing = 2; return ARM::VLD4q32;
Jim Grosbach7636bf62011-12-02 00:35:16 +00005576 }
5577}
5578
Jim Grosbach83ec8772011-11-10 23:42:14 +00005579bool ARMAsmParser::
Jim Grosbachf8fce712011-08-11 17:35:48 +00005580processInstruction(MCInst &Inst,
5581 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5582 switch (Inst.getOpcode()) {
Jim Grosbach0b4c6732012-01-18 22:46:46 +00005583 // Aliases for alternate PC+imm syntax of LDR instructions.
5584 case ARM::t2LDRpcrel:
5585 Inst.setOpcode(ARM::t2LDRpci);
5586 return true;
5587 case ARM::t2LDRBpcrel:
5588 Inst.setOpcode(ARM::t2LDRBpci);
5589 return true;
5590 case ARM::t2LDRHpcrel:
5591 Inst.setOpcode(ARM::t2LDRHpci);
5592 return true;
5593 case ARM::t2LDRSBpcrel:
5594 Inst.setOpcode(ARM::t2LDRSBpci);
5595 return true;
5596 case ARM::t2LDRSHpcrel:
5597 Inst.setOpcode(ARM::t2LDRSHpci);
5598 return true;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005599 // Handle NEON VST complex aliases.
Jim Grosbach8b31f952012-01-23 19:39:08 +00005600 case ARM::VST1LNdWB_register_Asm_8:
5601 case ARM::VST1LNdWB_register_Asm_16:
5602 case ARM::VST1LNdWB_register_Asm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005603 MCInst TmpInst;
5604 // Shuffle the operands around so the lane index operand is in the
5605 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005606 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005607 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005608 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5609 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5610 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5611 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5612 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5613 TmpInst.addOperand(Inst.getOperand(1)); // lane
5614 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5615 TmpInst.addOperand(Inst.getOperand(6));
5616 Inst = TmpInst;
5617 return true;
5618 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005619
Jim Grosbach8b31f952012-01-23 19:39:08 +00005620 case ARM::VST2LNdWB_register_Asm_8:
5621 case ARM::VST2LNdWB_register_Asm_16:
5622 case ARM::VST2LNdWB_register_Asm_32:
5623 case ARM::VST2LNqWB_register_Asm_16:
5624 case ARM::VST2LNqWB_register_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005625 MCInst TmpInst;
5626 // Shuffle the operands around so the lane index operand is in the
5627 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005628 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005629 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005630 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5631 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5632 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5633 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5634 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005635 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5636 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005637 TmpInst.addOperand(Inst.getOperand(1)); // lane
5638 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5639 TmpInst.addOperand(Inst.getOperand(6));
5640 Inst = TmpInst;
5641 return true;
5642 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005643
5644 case ARM::VST3LNdWB_register_Asm_8:
5645 case ARM::VST3LNdWB_register_Asm_16:
5646 case ARM::VST3LNdWB_register_Asm_32:
5647 case ARM::VST3LNqWB_register_Asm_16:
5648 case ARM::VST3LNqWB_register_Asm_32: {
5649 MCInst TmpInst;
5650 // Shuffle the operands around so the lane index operand is in the
5651 // right place.
5652 unsigned Spacing;
5653 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5654 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5655 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5656 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5657 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5658 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5659 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5660 Spacing));
5661 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5662 Spacing * 2));
5663 TmpInst.addOperand(Inst.getOperand(1)); // lane
5664 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5665 TmpInst.addOperand(Inst.getOperand(6));
5666 Inst = TmpInst;
5667 return true;
5668 }
5669
Jim Grosbach88a54de2012-01-24 18:53:13 +00005670 case ARM::VST4LNdWB_register_Asm_8:
5671 case ARM::VST4LNdWB_register_Asm_16:
5672 case ARM::VST4LNdWB_register_Asm_32:
5673 case ARM::VST4LNqWB_register_Asm_16:
5674 case ARM::VST4LNqWB_register_Asm_32: {
5675 MCInst TmpInst;
5676 // Shuffle the operands around so the lane index operand is in the
5677 // right place.
5678 unsigned Spacing;
5679 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5680 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5681 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5682 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5683 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5684 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5685 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5686 Spacing));
5687 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5688 Spacing * 2));
5689 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5690 Spacing * 3));
5691 TmpInst.addOperand(Inst.getOperand(1)); // lane
5692 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5693 TmpInst.addOperand(Inst.getOperand(6));
5694 Inst = TmpInst;
5695 return true;
5696 }
5697
Jim Grosbach8b31f952012-01-23 19:39:08 +00005698 case ARM::VST1LNdWB_fixed_Asm_8:
5699 case ARM::VST1LNdWB_fixed_Asm_16:
5700 case ARM::VST1LNdWB_fixed_Asm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005701 MCInst TmpInst;
5702 // Shuffle the operands around so the lane index operand is in the
5703 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005704 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005705 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005706 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5707 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5708 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5709 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5710 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5711 TmpInst.addOperand(Inst.getOperand(1)); // lane
5712 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5713 TmpInst.addOperand(Inst.getOperand(5));
5714 Inst = TmpInst;
5715 return true;
5716 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005717
Jim Grosbach8b31f952012-01-23 19:39:08 +00005718 case ARM::VST2LNdWB_fixed_Asm_8:
5719 case ARM::VST2LNdWB_fixed_Asm_16:
5720 case ARM::VST2LNdWB_fixed_Asm_32:
5721 case ARM::VST2LNqWB_fixed_Asm_16:
5722 case ARM::VST2LNqWB_fixed_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005723 MCInst TmpInst;
5724 // Shuffle the operands around so the lane index operand is in the
5725 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005726 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005727 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005728 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5729 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5730 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5731 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5732 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005733 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5734 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005735 TmpInst.addOperand(Inst.getOperand(1)); // lane
5736 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5737 TmpInst.addOperand(Inst.getOperand(5));
5738 Inst = TmpInst;
5739 return true;
5740 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005741
5742 case ARM::VST3LNdWB_fixed_Asm_8:
5743 case ARM::VST3LNdWB_fixed_Asm_16:
5744 case ARM::VST3LNdWB_fixed_Asm_32:
5745 case ARM::VST3LNqWB_fixed_Asm_16:
5746 case ARM::VST3LNqWB_fixed_Asm_32: {
5747 MCInst TmpInst;
5748 // Shuffle the operands around so the lane index operand is in the
5749 // right place.
5750 unsigned Spacing;
5751 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5752 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5753 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5754 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5755 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5756 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5757 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5758 Spacing));
5759 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5760 Spacing * 2));
5761 TmpInst.addOperand(Inst.getOperand(1)); // lane
5762 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5763 TmpInst.addOperand(Inst.getOperand(5));
5764 Inst = TmpInst;
5765 return true;
5766 }
5767
Jim Grosbach88a54de2012-01-24 18:53:13 +00005768 case ARM::VST4LNdWB_fixed_Asm_8:
5769 case ARM::VST4LNdWB_fixed_Asm_16:
5770 case ARM::VST4LNdWB_fixed_Asm_32:
5771 case ARM::VST4LNqWB_fixed_Asm_16:
5772 case ARM::VST4LNqWB_fixed_Asm_32: {
5773 MCInst TmpInst;
5774 // Shuffle the operands around so the lane index operand is in the
5775 // right place.
5776 unsigned Spacing;
5777 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5778 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5779 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5780 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5781 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5782 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5783 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5784 Spacing));
5785 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5786 Spacing * 2));
5787 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5788 Spacing * 3));
5789 TmpInst.addOperand(Inst.getOperand(1)); // lane
5790 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5791 TmpInst.addOperand(Inst.getOperand(5));
5792 Inst = TmpInst;
5793 return true;
5794 }
5795
Jim Grosbach8b31f952012-01-23 19:39:08 +00005796 case ARM::VST1LNdAsm_8:
5797 case ARM::VST1LNdAsm_16:
5798 case ARM::VST1LNdAsm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005799 MCInst TmpInst;
5800 // Shuffle the operands around so the lane index operand is in the
5801 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005802 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005803 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005804 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5805 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5806 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5807 TmpInst.addOperand(Inst.getOperand(1)); // lane
5808 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5809 TmpInst.addOperand(Inst.getOperand(5));
5810 Inst = TmpInst;
5811 return true;
5812 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005813
Jim Grosbach8b31f952012-01-23 19:39:08 +00005814 case ARM::VST2LNdAsm_8:
5815 case ARM::VST2LNdAsm_16:
5816 case ARM::VST2LNdAsm_32:
5817 case ARM::VST2LNqAsm_16:
5818 case ARM::VST2LNqAsm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005819 MCInst TmpInst;
5820 // Shuffle the operands around so the lane index operand is in the
5821 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005822 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005823 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005824 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5825 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5826 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005827 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5828 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005829 TmpInst.addOperand(Inst.getOperand(1)); // lane
5830 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5831 TmpInst.addOperand(Inst.getOperand(5));
5832 Inst = TmpInst;
5833 return true;
5834 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005835
5836 case ARM::VST3LNdAsm_8:
5837 case ARM::VST3LNdAsm_16:
5838 case ARM::VST3LNdAsm_32:
5839 case ARM::VST3LNqAsm_16:
5840 case ARM::VST3LNqAsm_32: {
5841 MCInst TmpInst;
5842 // Shuffle the operands around so the lane index operand is in the
5843 // right place.
5844 unsigned Spacing;
5845 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5846 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5847 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5848 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5849 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5850 Spacing));
5851 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5852 Spacing * 2));
5853 TmpInst.addOperand(Inst.getOperand(1)); // lane
5854 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5855 TmpInst.addOperand(Inst.getOperand(5));
5856 Inst = TmpInst;
5857 return true;
5858 }
5859
Jim Grosbach88a54de2012-01-24 18:53:13 +00005860 case ARM::VST4LNdAsm_8:
5861 case ARM::VST4LNdAsm_16:
5862 case ARM::VST4LNdAsm_32:
5863 case ARM::VST4LNqAsm_16:
5864 case ARM::VST4LNqAsm_32: {
5865 MCInst TmpInst;
5866 // Shuffle the operands around so the lane index operand is in the
5867 // right place.
5868 unsigned Spacing;
5869 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5870 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5871 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5872 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5873 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5874 Spacing));
5875 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5876 Spacing * 2));
5877 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5878 Spacing * 3));
5879 TmpInst.addOperand(Inst.getOperand(1)); // lane
5880 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5881 TmpInst.addOperand(Inst.getOperand(5));
5882 Inst = TmpInst;
5883 return true;
5884 }
5885
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005886 // Handle NEON VLD complex aliases.
Jim Grosbach8b31f952012-01-23 19:39:08 +00005887 case ARM::VLD1LNdWB_register_Asm_8:
5888 case ARM::VLD1LNdWB_register_Asm_16:
5889 case ARM::VLD1LNdWB_register_Asm_32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005890 MCInst TmpInst;
5891 // Shuffle the operands around so the lane index operand is in the
5892 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005893 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005894 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005895 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5896 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5897 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5898 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5899 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5900 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5901 TmpInst.addOperand(Inst.getOperand(1)); // lane
5902 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5903 TmpInst.addOperand(Inst.getOperand(6));
5904 Inst = TmpInst;
5905 return true;
5906 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005907
Jim Grosbach8b31f952012-01-23 19:39:08 +00005908 case ARM::VLD2LNdWB_register_Asm_8:
5909 case ARM::VLD2LNdWB_register_Asm_16:
5910 case ARM::VLD2LNdWB_register_Asm_32:
5911 case ARM::VLD2LNqWB_register_Asm_16:
5912 case ARM::VLD2LNqWB_register_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005913 MCInst TmpInst;
5914 // Shuffle the operands around so the lane index operand is in the
5915 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005916 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005917 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005918 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005919 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5920 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005921 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5922 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5923 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5924 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5925 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005926 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5927 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005928 TmpInst.addOperand(Inst.getOperand(1)); // lane
5929 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5930 TmpInst.addOperand(Inst.getOperand(6));
5931 Inst = TmpInst;
5932 return true;
5933 }
5934
Jim Grosbach3a678af2012-01-23 21:53:26 +00005935 case ARM::VLD3LNdWB_register_Asm_8:
5936 case ARM::VLD3LNdWB_register_Asm_16:
5937 case ARM::VLD3LNdWB_register_Asm_32:
5938 case ARM::VLD3LNqWB_register_Asm_16:
5939 case ARM::VLD3LNqWB_register_Asm_32: {
5940 MCInst TmpInst;
5941 // Shuffle the operands around so the lane index operand is in the
5942 // right place.
5943 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005944 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005945 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5946 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5947 Spacing));
5948 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005949 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005950 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5951 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5952 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5953 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5954 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5955 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5956 Spacing));
5957 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005958 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005959 TmpInst.addOperand(Inst.getOperand(1)); // lane
5960 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5961 TmpInst.addOperand(Inst.getOperand(6));
5962 Inst = TmpInst;
5963 return true;
5964 }
5965
Jim Grosbache983a132012-01-24 18:37:25 +00005966 case ARM::VLD4LNdWB_register_Asm_8:
5967 case ARM::VLD4LNdWB_register_Asm_16:
5968 case ARM::VLD4LNdWB_register_Asm_32:
5969 case ARM::VLD4LNqWB_register_Asm_16:
5970 case ARM::VLD4LNqWB_register_Asm_32: {
5971 MCInst TmpInst;
5972 // Shuffle the operands around so the lane index operand is in the
5973 // right place.
5974 unsigned Spacing;
5975 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
5976 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5977 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5978 Spacing));
5979 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5980 Spacing * 2));
5981 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5982 Spacing * 3));
5983 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5984 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5985 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5986 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5987 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5988 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5989 Spacing));
5990 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5991 Spacing * 2));
5992 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5993 Spacing * 3));
5994 TmpInst.addOperand(Inst.getOperand(1)); // lane
5995 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5996 TmpInst.addOperand(Inst.getOperand(6));
5997 Inst = TmpInst;
5998 return true;
5999 }
6000
Jim Grosbach8b31f952012-01-23 19:39:08 +00006001 case ARM::VLD1LNdWB_fixed_Asm_8:
6002 case ARM::VLD1LNdWB_fixed_Asm_16:
6003 case ARM::VLD1LNdWB_fixed_Asm_32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00006004 MCInst TmpInst;
6005 // Shuffle the operands around so the lane index operand is in the
6006 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006007 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006008 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00006009 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6010 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6011 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6012 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6013 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6014 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6015 TmpInst.addOperand(Inst.getOperand(1)); // lane
6016 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6017 TmpInst.addOperand(Inst.getOperand(5));
6018 Inst = TmpInst;
6019 return true;
6020 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006021
Jim Grosbach8b31f952012-01-23 19:39:08 +00006022 case ARM::VLD2LNdWB_fixed_Asm_8:
6023 case ARM::VLD2LNdWB_fixed_Asm_16:
6024 case ARM::VLD2LNdWB_fixed_Asm_32:
6025 case ARM::VLD2LNqWB_fixed_Asm_16:
6026 case ARM::VLD2LNqWB_fixed_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006027 MCInst TmpInst;
6028 // Shuffle the operands around so the lane index operand is in the
6029 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006030 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006031 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006032 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006033 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6034 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006035 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6036 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6037 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6038 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6039 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006040 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6041 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006042 TmpInst.addOperand(Inst.getOperand(1)); // lane
6043 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6044 TmpInst.addOperand(Inst.getOperand(5));
6045 Inst = TmpInst;
6046 return true;
6047 }
6048
Jim Grosbach3a678af2012-01-23 21:53:26 +00006049 case ARM::VLD3LNdWB_fixed_Asm_8:
6050 case ARM::VLD3LNdWB_fixed_Asm_16:
6051 case ARM::VLD3LNdWB_fixed_Asm_32:
6052 case ARM::VLD3LNqWB_fixed_Asm_16:
6053 case ARM::VLD3LNqWB_fixed_Asm_32: {
6054 MCInst TmpInst;
6055 // Shuffle the operands around so the lane index operand is in the
6056 // right place.
6057 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006058 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006059 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6060 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6061 Spacing));
6062 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006063 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006064 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6065 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6066 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6067 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6068 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6069 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6070 Spacing));
6071 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006072 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006073 TmpInst.addOperand(Inst.getOperand(1)); // lane
6074 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6075 TmpInst.addOperand(Inst.getOperand(5));
6076 Inst = TmpInst;
6077 return true;
6078 }
6079
Jim Grosbache983a132012-01-24 18:37:25 +00006080 case ARM::VLD4LNdWB_fixed_Asm_8:
6081 case ARM::VLD4LNdWB_fixed_Asm_16:
6082 case ARM::VLD4LNdWB_fixed_Asm_32:
6083 case ARM::VLD4LNqWB_fixed_Asm_16:
6084 case ARM::VLD4LNqWB_fixed_Asm_32: {
6085 MCInst TmpInst;
6086 // Shuffle the operands around so the lane index operand is in the
6087 // right place.
6088 unsigned Spacing;
6089 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6090 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6091 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6092 Spacing));
6093 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6094 Spacing * 2));
6095 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6096 Spacing * 3));
6097 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6098 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6099 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6100 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6101 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6102 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6103 Spacing));
6104 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6105 Spacing * 2));
6106 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6107 Spacing * 3));
6108 TmpInst.addOperand(Inst.getOperand(1)); // lane
6109 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6110 TmpInst.addOperand(Inst.getOperand(5));
6111 Inst = TmpInst;
6112 return true;
6113 }
6114
Jim Grosbach8b31f952012-01-23 19:39:08 +00006115 case ARM::VLD1LNdAsm_8:
6116 case ARM::VLD1LNdAsm_16:
6117 case ARM::VLD1LNdAsm_32: {
Jim Grosbach7636bf62011-12-02 00:35:16 +00006118 MCInst TmpInst;
6119 // Shuffle the operands around so the lane index operand is in the
6120 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006121 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006122 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach7636bf62011-12-02 00:35:16 +00006123 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6124 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6125 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6126 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6127 TmpInst.addOperand(Inst.getOperand(1)); // lane
6128 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6129 TmpInst.addOperand(Inst.getOperand(5));
6130 Inst = TmpInst;
6131 return true;
6132 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006133
Jim Grosbach8b31f952012-01-23 19:39:08 +00006134 case ARM::VLD2LNdAsm_8:
6135 case ARM::VLD2LNdAsm_16:
6136 case ARM::VLD2LNdAsm_32:
6137 case ARM::VLD2LNqAsm_16:
6138 case ARM::VLD2LNqAsm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006139 MCInst TmpInst;
6140 // Shuffle the operands around so the lane index operand is in the
6141 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006142 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006143 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006144 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006145 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6146 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006147 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6148 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6149 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006150 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6151 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006152 TmpInst.addOperand(Inst.getOperand(1)); // lane
6153 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6154 TmpInst.addOperand(Inst.getOperand(5));
6155 Inst = TmpInst;
6156 return true;
6157 }
Jim Grosbach3a678af2012-01-23 21:53:26 +00006158
6159 case ARM::VLD3LNdAsm_8:
6160 case ARM::VLD3LNdAsm_16:
6161 case ARM::VLD3LNdAsm_32:
6162 case ARM::VLD3LNqAsm_16:
6163 case ARM::VLD3LNqAsm_32: {
6164 MCInst TmpInst;
6165 // Shuffle the operands around so the lane index operand is in the
6166 // right place.
6167 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006168 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006169 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6170 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6171 Spacing));
6172 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006173 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006174 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6175 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6176 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6177 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6178 Spacing));
6179 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006180 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006181 TmpInst.addOperand(Inst.getOperand(1)); // lane
6182 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6183 TmpInst.addOperand(Inst.getOperand(5));
6184 Inst = TmpInst;
6185 return true;
6186 }
6187
Jim Grosbache983a132012-01-24 18:37:25 +00006188 case ARM::VLD4LNdAsm_8:
6189 case ARM::VLD4LNdAsm_16:
6190 case ARM::VLD4LNdAsm_32:
6191 case ARM::VLD4LNqAsm_16:
6192 case ARM::VLD4LNqAsm_32: {
6193 MCInst TmpInst;
6194 // Shuffle the operands around so the lane index operand is in the
6195 // right place.
6196 unsigned Spacing;
6197 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6198 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6199 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6200 Spacing));
6201 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6202 Spacing * 2));
6203 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6204 Spacing * 3));
6205 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6206 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6207 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6208 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6209 Spacing));
6210 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6211 Spacing * 2));
6212 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6213 Spacing * 3));
6214 TmpInst.addOperand(Inst.getOperand(1)); // lane
6215 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6216 TmpInst.addOperand(Inst.getOperand(5));
6217 Inst = TmpInst;
6218 return true;
6219 }
6220
Jim Grosbach5e59f7e2012-01-24 23:47:04 +00006221 // VLD3DUP single 3-element structure to all lanes instructions.
6222 case ARM::VLD3DUPdAsm_8:
6223 case ARM::VLD3DUPdAsm_16:
6224 case ARM::VLD3DUPdAsm_32:
6225 case ARM::VLD3DUPqAsm_8:
6226 case ARM::VLD3DUPqAsm_16:
6227 case ARM::VLD3DUPqAsm_32: {
6228 MCInst TmpInst;
6229 unsigned Spacing;
6230 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6231 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6232 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6233 Spacing));
6234 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6235 Spacing * 2));
6236 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6237 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6238 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6239 TmpInst.addOperand(Inst.getOperand(4));
6240 Inst = TmpInst;
6241 return true;
6242 }
6243
6244 case ARM::VLD3DUPdWB_fixed_Asm_8:
6245 case ARM::VLD3DUPdWB_fixed_Asm_16:
6246 case ARM::VLD3DUPdWB_fixed_Asm_32:
6247 case ARM::VLD3DUPqWB_fixed_Asm_8:
6248 case ARM::VLD3DUPqWB_fixed_Asm_16:
6249 case ARM::VLD3DUPqWB_fixed_Asm_32: {
6250 MCInst TmpInst;
6251 unsigned Spacing;
6252 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6253 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6254 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6255 Spacing));
6256 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6257 Spacing * 2));
6258 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6259 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6260 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6261 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6262 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6263 TmpInst.addOperand(Inst.getOperand(4));
6264 Inst = TmpInst;
6265 return true;
6266 }
6267
6268 case ARM::VLD3DUPdWB_register_Asm_8:
6269 case ARM::VLD3DUPdWB_register_Asm_16:
6270 case ARM::VLD3DUPdWB_register_Asm_32:
6271 case ARM::VLD3DUPqWB_register_Asm_8:
6272 case ARM::VLD3DUPqWB_register_Asm_16:
6273 case ARM::VLD3DUPqWB_register_Asm_32: {
6274 MCInst TmpInst;
6275 unsigned Spacing;
6276 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6277 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6278 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6279 Spacing));
6280 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6281 Spacing * 2));
6282 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6283 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6284 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6285 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6286 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6287 TmpInst.addOperand(Inst.getOperand(5));
6288 Inst = TmpInst;
6289 return true;
6290 }
6291
Jim Grosbachc387fc62012-01-23 23:20:46 +00006292 // VLD3 multiple 3-element structure instructions.
6293 case ARM::VLD3dAsm_8:
6294 case ARM::VLD3dAsm_16:
6295 case ARM::VLD3dAsm_32:
6296 case ARM::VLD3qAsm_8:
6297 case ARM::VLD3qAsm_16:
6298 case ARM::VLD3qAsm_32: {
6299 MCInst TmpInst;
6300 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006301 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00006302 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6303 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6304 Spacing));
6305 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6306 Spacing * 2));
6307 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6308 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6309 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6310 TmpInst.addOperand(Inst.getOperand(4));
6311 Inst = TmpInst;
6312 return true;
6313 }
6314
6315 case ARM::VLD3dWB_fixed_Asm_8:
6316 case ARM::VLD3dWB_fixed_Asm_16:
6317 case ARM::VLD3dWB_fixed_Asm_32:
6318 case ARM::VLD3qWB_fixed_Asm_8:
6319 case ARM::VLD3qWB_fixed_Asm_16:
6320 case ARM::VLD3qWB_fixed_Asm_32: {
6321 MCInst TmpInst;
6322 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006323 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00006324 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6325 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6326 Spacing));
6327 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6328 Spacing * 2));
6329 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6330 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6331 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6332 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6333 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6334 TmpInst.addOperand(Inst.getOperand(4));
6335 Inst = TmpInst;
6336 return true;
6337 }
6338
6339 case ARM::VLD3dWB_register_Asm_8:
6340 case ARM::VLD3dWB_register_Asm_16:
6341 case ARM::VLD3dWB_register_Asm_32:
6342 case ARM::VLD3qWB_register_Asm_8:
6343 case ARM::VLD3qWB_register_Asm_16:
6344 case ARM::VLD3qWB_register_Asm_32: {
6345 MCInst TmpInst;
6346 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006347 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00006348 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6349 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6350 Spacing));
6351 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6352 Spacing * 2));
6353 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6354 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6355 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6356 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6357 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6358 TmpInst.addOperand(Inst.getOperand(5));
6359 Inst = TmpInst;
6360 return true;
6361 }
6362
Jim Grosbacha57a36a2012-01-25 00:01:08 +00006363 // VLD4DUP single 3-element structure to all lanes instructions.
6364 case ARM::VLD4DUPdAsm_8:
6365 case ARM::VLD4DUPdAsm_16:
6366 case ARM::VLD4DUPdAsm_32:
6367 case ARM::VLD4DUPqAsm_8:
6368 case ARM::VLD4DUPqAsm_16:
6369 case ARM::VLD4DUPqAsm_32: {
6370 MCInst TmpInst;
6371 unsigned Spacing;
6372 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6373 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6374 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6375 Spacing));
6376 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6377 Spacing * 2));
6378 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6379 Spacing * 3));
6380 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6381 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6382 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6383 TmpInst.addOperand(Inst.getOperand(4));
6384 Inst = TmpInst;
6385 return true;
6386 }
6387
6388 case ARM::VLD4DUPdWB_fixed_Asm_8:
6389 case ARM::VLD4DUPdWB_fixed_Asm_16:
6390 case ARM::VLD4DUPdWB_fixed_Asm_32:
6391 case ARM::VLD4DUPqWB_fixed_Asm_8:
6392 case ARM::VLD4DUPqWB_fixed_Asm_16:
6393 case ARM::VLD4DUPqWB_fixed_Asm_32: {
6394 MCInst TmpInst;
6395 unsigned Spacing;
6396 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6397 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6398 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6399 Spacing));
6400 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6401 Spacing * 2));
6402 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6403 Spacing * 3));
6404 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6405 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6406 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6407 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6408 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6409 TmpInst.addOperand(Inst.getOperand(4));
6410 Inst = TmpInst;
6411 return true;
6412 }
6413
6414 case ARM::VLD4DUPdWB_register_Asm_8:
6415 case ARM::VLD4DUPdWB_register_Asm_16:
6416 case ARM::VLD4DUPdWB_register_Asm_32:
6417 case ARM::VLD4DUPqWB_register_Asm_8:
6418 case ARM::VLD4DUPqWB_register_Asm_16:
6419 case ARM::VLD4DUPqWB_register_Asm_32: {
6420 MCInst TmpInst;
6421 unsigned Spacing;
6422 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6423 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6424 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6425 Spacing));
6426 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6427 Spacing * 2));
6428 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6429 Spacing * 3));
6430 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6431 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6432 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6433 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6434 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6435 TmpInst.addOperand(Inst.getOperand(5));
6436 Inst = TmpInst;
6437 return true;
6438 }
6439
6440 // VLD4 multiple 4-element structure instructions.
Jim Grosbach8abe7e32012-01-24 00:43:17 +00006441 case ARM::VLD4dAsm_8:
6442 case ARM::VLD4dAsm_16:
6443 case ARM::VLD4dAsm_32:
6444 case ARM::VLD4qAsm_8:
6445 case ARM::VLD4qAsm_16:
6446 case ARM::VLD4qAsm_32: {
6447 MCInst TmpInst;
6448 unsigned Spacing;
6449 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6450 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6451 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6452 Spacing));
6453 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6454 Spacing * 2));
6455 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6456 Spacing * 3));
6457 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6458 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6459 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6460 TmpInst.addOperand(Inst.getOperand(4));
6461 Inst = TmpInst;
6462 return true;
6463 }
6464
6465 case ARM::VLD4dWB_fixed_Asm_8:
6466 case ARM::VLD4dWB_fixed_Asm_16:
6467 case ARM::VLD4dWB_fixed_Asm_32:
6468 case ARM::VLD4qWB_fixed_Asm_8:
6469 case ARM::VLD4qWB_fixed_Asm_16:
6470 case ARM::VLD4qWB_fixed_Asm_32: {
6471 MCInst TmpInst;
6472 unsigned Spacing;
6473 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6474 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6475 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6476 Spacing));
6477 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6478 Spacing * 2));
6479 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6480 Spacing * 3));
6481 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6482 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6483 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6484 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6485 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6486 TmpInst.addOperand(Inst.getOperand(4));
6487 Inst = TmpInst;
6488 return true;
6489 }
6490
6491 case ARM::VLD4dWB_register_Asm_8:
6492 case ARM::VLD4dWB_register_Asm_16:
6493 case ARM::VLD4dWB_register_Asm_32:
6494 case ARM::VLD4qWB_register_Asm_8:
6495 case ARM::VLD4qWB_register_Asm_16:
6496 case ARM::VLD4qWB_register_Asm_32: {
6497 MCInst TmpInst;
6498 unsigned Spacing;
6499 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6500 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6501 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6502 Spacing));
6503 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6504 Spacing * 2));
6505 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6506 Spacing * 3));
6507 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6508 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6509 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6510 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6511 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6512 TmpInst.addOperand(Inst.getOperand(5));
6513 Inst = TmpInst;
6514 return true;
6515 }
6516
Jim Grosbachd7433e22012-01-23 23:45:44 +00006517 // VST3 multiple 3-element structure instructions.
6518 case ARM::VST3dAsm_8:
6519 case ARM::VST3dAsm_16:
6520 case ARM::VST3dAsm_32:
6521 case ARM::VST3qAsm_8:
6522 case ARM::VST3qAsm_16:
6523 case ARM::VST3qAsm_32: {
6524 MCInst TmpInst;
6525 unsigned Spacing;
6526 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6527 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6528 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6529 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6530 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6531 Spacing));
6532 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6533 Spacing * 2));
6534 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6535 TmpInst.addOperand(Inst.getOperand(4));
6536 Inst = TmpInst;
6537 return true;
6538 }
6539
6540 case ARM::VST3dWB_fixed_Asm_8:
6541 case ARM::VST3dWB_fixed_Asm_16:
6542 case ARM::VST3dWB_fixed_Asm_32:
6543 case ARM::VST3qWB_fixed_Asm_8:
6544 case ARM::VST3qWB_fixed_Asm_16:
6545 case ARM::VST3qWB_fixed_Asm_32: {
6546 MCInst TmpInst;
6547 unsigned Spacing;
6548 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6549 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6550 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6551 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6552 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6553 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6554 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6555 Spacing));
6556 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6557 Spacing * 2));
6558 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6559 TmpInst.addOperand(Inst.getOperand(4));
6560 Inst = TmpInst;
6561 return true;
6562 }
6563
6564 case ARM::VST3dWB_register_Asm_8:
6565 case ARM::VST3dWB_register_Asm_16:
6566 case ARM::VST3dWB_register_Asm_32:
6567 case ARM::VST3qWB_register_Asm_8:
6568 case ARM::VST3qWB_register_Asm_16:
6569 case ARM::VST3qWB_register_Asm_32: {
6570 MCInst TmpInst;
6571 unsigned Spacing;
6572 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6573 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6574 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6575 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6576 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6577 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6578 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6579 Spacing));
6580 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6581 Spacing * 2));
6582 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6583 TmpInst.addOperand(Inst.getOperand(5));
6584 Inst = TmpInst;
6585 return true;
6586 }
6587
Jim Grosbach539aab72012-01-24 00:58:13 +00006588 // VST4 multiple 3-element structure instructions.
6589 case ARM::VST4dAsm_8:
6590 case ARM::VST4dAsm_16:
6591 case ARM::VST4dAsm_32:
6592 case ARM::VST4qAsm_8:
6593 case ARM::VST4qAsm_16:
6594 case ARM::VST4qAsm_32: {
6595 MCInst TmpInst;
6596 unsigned Spacing;
6597 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6598 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6599 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6600 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6601 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6602 Spacing));
6603 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6604 Spacing * 2));
6605 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6606 Spacing * 3));
6607 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6608 TmpInst.addOperand(Inst.getOperand(4));
6609 Inst = TmpInst;
6610 return true;
6611 }
6612
6613 case ARM::VST4dWB_fixed_Asm_8:
6614 case ARM::VST4dWB_fixed_Asm_16:
6615 case ARM::VST4dWB_fixed_Asm_32:
6616 case ARM::VST4qWB_fixed_Asm_8:
6617 case ARM::VST4qWB_fixed_Asm_16:
6618 case ARM::VST4qWB_fixed_Asm_32: {
6619 MCInst TmpInst;
6620 unsigned Spacing;
6621 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6622 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6623 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6624 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6625 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6626 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6627 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6628 Spacing));
6629 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6630 Spacing * 2));
6631 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6632 Spacing * 3));
6633 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6634 TmpInst.addOperand(Inst.getOperand(4));
6635 Inst = TmpInst;
6636 return true;
6637 }
6638
6639 case ARM::VST4dWB_register_Asm_8:
6640 case ARM::VST4dWB_register_Asm_16:
6641 case ARM::VST4dWB_register_Asm_32:
6642 case ARM::VST4qWB_register_Asm_8:
6643 case ARM::VST4qWB_register_Asm_16:
6644 case ARM::VST4qWB_register_Asm_32: {
6645 MCInst TmpInst;
6646 unsigned Spacing;
6647 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6648 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6649 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6650 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6651 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6652 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6653 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6654 Spacing));
6655 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6656 Spacing * 2));
6657 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6658 Spacing * 3));
6659 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6660 TmpInst.addOperand(Inst.getOperand(5));
6661 Inst = TmpInst;
6662 return true;
6663 }
6664
Jim Grosbacha5378eb2012-04-11 00:15:16 +00006665 // Handle encoding choice for the shift-immediate instructions.
6666 case ARM::t2LSLri:
6667 case ARM::t2LSRri:
6668 case ARM::t2ASRri: {
6669 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6670 Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
6671 Inst.getOperand(5).getReg() == (inITBlock() ? 0 : ARM::CPSR) &&
6672 !(static_cast<ARMOperand*>(Operands[3])->isToken() &&
6673 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w")) {
6674 unsigned NewOpc;
6675 switch (Inst.getOpcode()) {
6676 default: llvm_unreachable("unexpected opcode");
6677 case ARM::t2LSLri: NewOpc = ARM::tLSLri; break;
6678 case ARM::t2LSRri: NewOpc = ARM::tLSRri; break;
6679 case ARM::t2ASRri: NewOpc = ARM::tASRri; break;
6680 }
6681 // The Thumb1 operands aren't in the same order. Awesome, eh?
6682 MCInst TmpInst;
6683 TmpInst.setOpcode(NewOpc);
6684 TmpInst.addOperand(Inst.getOperand(0));
6685 TmpInst.addOperand(Inst.getOperand(5));
6686 TmpInst.addOperand(Inst.getOperand(1));
6687 TmpInst.addOperand(Inst.getOperand(2));
6688 TmpInst.addOperand(Inst.getOperand(3));
6689 TmpInst.addOperand(Inst.getOperand(4));
6690 Inst = TmpInst;
6691 return true;
6692 }
6693 return false;
6694 }
6695
Jim Grosbach863d2af2011-12-13 22:45:11 +00006696 // Handle the Thumb2 mode MOV complex aliases.
Jim Grosbach2cc5cda2011-12-21 20:54:00 +00006697 case ARM::t2MOVsr:
6698 case ARM::t2MOVSsr: {
6699 // Which instruction to expand to depends on the CCOut operand and
6700 // whether we're in an IT block if the register operands are low
6701 // registers.
6702 bool isNarrow = false;
6703 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6704 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6705 isARMLowRegister(Inst.getOperand(2).getReg()) &&
6706 Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
6707 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsr))
6708 isNarrow = true;
6709 MCInst TmpInst;
6710 unsigned newOpc;
6711 switch(ARM_AM::getSORegShOp(Inst.getOperand(3).getImm())) {
6712 default: llvm_unreachable("unexpected opcode!");
6713 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRrr : ARM::t2ASRrr; break;
6714 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRrr : ARM::t2LSRrr; break;
6715 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLrr : ARM::t2LSLrr; break;
6716 case ARM_AM::ror: newOpc = isNarrow ? ARM::tROR : ARM::t2RORrr; break;
6717 }
6718 TmpInst.setOpcode(newOpc);
6719 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6720 if (isNarrow)
6721 TmpInst.addOperand(MCOperand::CreateReg(
6722 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6723 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6724 TmpInst.addOperand(Inst.getOperand(2)); // Rm
6725 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6726 TmpInst.addOperand(Inst.getOperand(5));
6727 if (!isNarrow)
6728 TmpInst.addOperand(MCOperand::CreateReg(
6729 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6730 Inst = TmpInst;
6731 return true;
6732 }
Jim Grosbach863d2af2011-12-13 22:45:11 +00006733 case ARM::t2MOVsi:
6734 case ARM::t2MOVSsi: {
6735 // Which instruction to expand to depends on the CCOut operand and
6736 // whether we're in an IT block if the register operands are low
6737 // registers.
6738 bool isNarrow = false;
6739 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6740 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6741 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
6742 isNarrow = true;
6743 MCInst TmpInst;
6744 unsigned newOpc;
6745 switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
6746 default: llvm_unreachable("unexpected opcode!");
6747 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
6748 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
6749 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
6750 case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
Jim Grosbach520dc782011-12-21 21:04:19 +00006751 case ARM_AM::rrx: isNarrow = false; newOpc = ARM::t2RRX; break;
Jim Grosbach863d2af2011-12-13 22:45:11 +00006752 }
6753 unsigned Ammount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
6754 if (Ammount == 32) Ammount = 0;
6755 TmpInst.setOpcode(newOpc);
6756 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6757 if (isNarrow)
6758 TmpInst.addOperand(MCOperand::CreateReg(
6759 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6760 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbach520dc782011-12-21 21:04:19 +00006761 if (newOpc != ARM::t2RRX)
6762 TmpInst.addOperand(MCOperand::CreateImm(Ammount));
Jim Grosbach863d2af2011-12-13 22:45:11 +00006763 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6764 TmpInst.addOperand(Inst.getOperand(4));
6765 if (!isNarrow)
6766 TmpInst.addOperand(MCOperand::CreateReg(
6767 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6768 Inst = TmpInst;
6769 return true;
6770 }
6771 // Handle the ARM mode MOV complex aliases.
Jim Grosbach23f22072011-11-16 18:31:45 +00006772 case ARM::ASRr:
6773 case ARM::LSRr:
6774 case ARM::LSLr:
6775 case ARM::RORr: {
6776 ARM_AM::ShiftOpc ShiftTy;
6777 switch(Inst.getOpcode()) {
6778 default: llvm_unreachable("unexpected opcode!");
6779 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
6780 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
6781 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
6782 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
6783 }
Jim Grosbach23f22072011-11-16 18:31:45 +00006784 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
6785 MCInst TmpInst;
6786 TmpInst.setOpcode(ARM::MOVsr);
6787 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6788 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6789 TmpInst.addOperand(Inst.getOperand(2)); // Rm
6790 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6791 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6792 TmpInst.addOperand(Inst.getOperand(4));
6793 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6794 Inst = TmpInst;
6795 return true;
6796 }
Jim Grosbachee10ff82011-11-10 19:18:01 +00006797 case ARM::ASRi:
6798 case ARM::LSRi:
6799 case ARM::LSLi:
6800 case ARM::RORi: {
6801 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachee10ff82011-11-10 19:18:01 +00006802 switch(Inst.getOpcode()) {
6803 default: llvm_unreachable("unexpected opcode!");
6804 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
6805 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
6806 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
6807 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
6808 }
6809 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach48b368b2011-11-16 19:05:59 +00006810 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachee10ff82011-11-10 19:18:01 +00006811 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
6812 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach71810ab2011-11-10 16:44:55 +00006813 MCInst TmpInst;
Jim Grosbachee10ff82011-11-10 19:18:01 +00006814 TmpInst.setOpcode(Opc);
Jim Grosbach71810ab2011-11-10 16:44:55 +00006815 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6816 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachee10ff82011-11-10 19:18:01 +00006817 if (Opc == ARM::MOVsi)
6818 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach71810ab2011-11-10 16:44:55 +00006819 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6820 TmpInst.addOperand(Inst.getOperand(4));
6821 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6822 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006823 return true;
Jim Grosbach71810ab2011-11-10 16:44:55 +00006824 }
Jim Grosbach48b368b2011-11-16 19:05:59 +00006825 case ARM::RRXi: {
6826 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
6827 MCInst TmpInst;
6828 TmpInst.setOpcode(ARM::MOVsi);
6829 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6830 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6831 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6832 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6833 TmpInst.addOperand(Inst.getOperand(3));
6834 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
6835 Inst = TmpInst;
6836 return true;
6837 }
Jim Grosbach0352b462011-11-10 23:58:34 +00006838 case ARM::t2LDMIA_UPD: {
6839 // If this is a load of a single register, then we should use
6840 // a post-indexed LDR instruction instead, per the ARM ARM.
6841 if (Inst.getNumOperands() != 5)
6842 return false;
6843 MCInst TmpInst;
6844 TmpInst.setOpcode(ARM::t2LDR_POST);
6845 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6846 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6847 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6848 TmpInst.addOperand(MCOperand::CreateImm(4));
6849 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6850 TmpInst.addOperand(Inst.getOperand(3));
6851 Inst = TmpInst;
6852 return true;
6853 }
6854 case ARM::t2STMDB_UPD: {
6855 // If this is a store of a single register, then we should use
6856 // a pre-indexed STR instruction instead, per the ARM ARM.
6857 if (Inst.getNumOperands() != 5)
6858 return false;
6859 MCInst TmpInst;
6860 TmpInst.setOpcode(ARM::t2STR_PRE);
6861 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6862 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6863 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6864 TmpInst.addOperand(MCOperand::CreateImm(-4));
6865 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6866 TmpInst.addOperand(Inst.getOperand(3));
6867 Inst = TmpInst;
6868 return true;
6869 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00006870 case ARM::LDMIA_UPD:
6871 // If this is a load of a single register via a 'pop', then we should use
6872 // a post-indexed LDR instruction instead, per the ARM ARM.
6873 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
6874 Inst.getNumOperands() == 5) {
6875 MCInst TmpInst;
6876 TmpInst.setOpcode(ARM::LDR_POST_IMM);
6877 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6878 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6879 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6880 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
6881 TmpInst.addOperand(MCOperand::CreateImm(4));
6882 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6883 TmpInst.addOperand(Inst.getOperand(3));
6884 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006885 return true;
Jim Grosbachf8fce712011-08-11 17:35:48 +00006886 }
6887 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00006888 case ARM::STMDB_UPD:
6889 // If this is a store of a single register via a 'push', then we should use
6890 // a pre-indexed STR instruction instead, per the ARM ARM.
6891 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
6892 Inst.getNumOperands() == 5) {
6893 MCInst TmpInst;
6894 TmpInst.setOpcode(ARM::STR_PRE_IMM);
6895 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6896 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6897 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
6898 TmpInst.addOperand(MCOperand::CreateImm(-4));
6899 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6900 TmpInst.addOperand(Inst.getOperand(3));
6901 Inst = TmpInst;
6902 }
6903 break;
Jim Grosbachda847862011-12-05 21:06:26 +00006904 case ARM::t2ADDri12:
6905 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
6906 // mnemonic was used (not "addw"), encoding T3 is preferred.
6907 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
6908 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
6909 break;
6910 Inst.setOpcode(ARM::t2ADDri);
6911 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
6912 break;
6913 case ARM::t2SUBri12:
6914 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
6915 // mnemonic was used (not "subw"), encoding T3 is preferred.
6916 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
6917 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
6918 break;
6919 Inst.setOpcode(ARM::t2SUBri);
6920 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
6921 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006922 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00006923 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6924 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6925 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6926 // to encoding T1 if <Rd> is omitted."
Jim Grosbachc0164f82012-03-30 16:31:31 +00006927 if ((unsigned)Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006928 Inst.setOpcode(ARM::tADDi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006929 return true;
6930 }
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006931 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00006932 case ARM::tSUBi8:
6933 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6934 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6935 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6936 // to encoding T1 if <Rd> is omitted."
Jim Grosbachc0164f82012-03-30 16:31:31 +00006937 if ((unsigned)Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachf67e8552011-09-16 22:58:42 +00006938 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006939 return true;
6940 }
Jim Grosbachf67e8552011-09-16 22:58:42 +00006941 break;
Jim Grosbach2d30d942012-03-30 17:20:40 +00006942 case ARM::t2ADDri:
6943 case ARM::t2SUBri: {
6944 // If the destination and first source operand are the same, and
6945 // the flags are compatible with the current IT status, use encoding T2
6946 // instead of T3. For compatibility with the system 'as'. Make sure the
6947 // wide encoding wasn't explicit.
6948 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
Jim Grosbach8f1148b2012-03-30 18:39:43 +00006949 !isARMLowRegister(Inst.getOperand(0).getReg()) ||
Jim Grosbach2d30d942012-03-30 17:20:40 +00006950 (unsigned)Inst.getOperand(2).getImm() > 255 ||
6951 ((!inITBlock() && Inst.getOperand(5).getReg() != ARM::CPSR) ||
6952 (inITBlock() && Inst.getOperand(5).getReg() != 0)) ||
6953 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6954 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
6955 break;
6956 MCInst TmpInst;
6957 TmpInst.setOpcode(Inst.getOpcode() == ARM::t2ADDri ?
6958 ARM::tADDi8 : ARM::tSUBi8);
6959 TmpInst.addOperand(Inst.getOperand(0));
6960 TmpInst.addOperand(Inst.getOperand(5));
6961 TmpInst.addOperand(Inst.getOperand(0));
6962 TmpInst.addOperand(Inst.getOperand(2));
6963 TmpInst.addOperand(Inst.getOperand(3));
6964 TmpInst.addOperand(Inst.getOperand(4));
6965 Inst = TmpInst;
6966 return true;
6967 }
Jim Grosbach927b9df2011-12-05 22:16:39 +00006968 case ARM::t2ADDrr: {
6969 // If the destination and first source operand are the same, and
6970 // there's no setting of the flags, use encoding T2 instead of T3.
6971 // Note that this is only for ADD, not SUB. This mirrors the system
6972 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
6973 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
6974 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbach713c7022011-12-05 22:27:04 +00006975 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6976 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbach927b9df2011-12-05 22:16:39 +00006977 break;
6978 MCInst TmpInst;
6979 TmpInst.setOpcode(ARM::tADDhirr);
6980 TmpInst.addOperand(Inst.getOperand(0));
6981 TmpInst.addOperand(Inst.getOperand(0));
6982 TmpInst.addOperand(Inst.getOperand(2));
6983 TmpInst.addOperand(Inst.getOperand(3));
6984 TmpInst.addOperand(Inst.getOperand(4));
6985 Inst = TmpInst;
6986 return true;
6987 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006988 case ARM::tB:
6989 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006990 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006991 Inst.setOpcode(ARM::tBcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006992 return true;
6993 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006994 break;
6995 case ARM::t2B:
6996 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006997 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006998 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006999 return true;
7000 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00007001 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00007002 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00007003 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbach83ec8772011-11-10 23:42:14 +00007004 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbachc0755102011-08-31 21:17:31 +00007005 Inst.setOpcode(ARM::t2B);
Jim Grosbach83ec8772011-11-10 23:42:14 +00007006 return true;
7007 }
Jim Grosbachc0755102011-08-31 21:17:31 +00007008 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00007009 case ARM::tBcc:
7010 // If the conditional is AL, we really want tB.
Jim Grosbach83ec8772011-11-10 23:42:14 +00007011 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbach395b4532011-08-17 22:57:40 +00007012 Inst.setOpcode(ARM::tB);
Jim Grosbach83ec8772011-11-10 23:42:14 +00007013 return true;
7014 }
Jim Grosbach3ce23d32011-08-18 16:08:39 +00007015 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00007016 case ARM::tLDMIA: {
7017 // If the register list contains any high registers, or if the writeback
7018 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
7019 // instead if we're in Thumb2. Otherwise, this should have generated
7020 // an error in validateInstruction().
7021 unsigned Rn = Inst.getOperand(0).getReg();
7022 bool hasWritebackToken =
7023 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
7024 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
7025 bool listContainsBase;
7026 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
7027 (!listContainsBase && !hasWritebackToken) ||
7028 (listContainsBase && hasWritebackToken)) {
7029 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
7030 assert (isThumbTwo());
7031 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
7032 // If we're switching to the updating version, we need to insert
7033 // the writeback tied operand.
7034 if (hasWritebackToken)
7035 Inst.insert(Inst.begin(),
7036 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbach83ec8772011-11-10 23:42:14 +00007037 return true;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00007038 }
7039 break;
7040 }
Jim Grosbach8213c962011-09-16 20:50:13 +00007041 case ARM::tSTMIA_UPD: {
7042 // If the register list contains any high registers, we need to use
7043 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
7044 // should have generated an error in validateInstruction().
7045 unsigned Rn = Inst.getOperand(0).getReg();
7046 bool listContainsBase;
7047 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
7048 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
7049 assert (isThumbTwo());
7050 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbach83ec8772011-11-10 23:42:14 +00007051 return true;
Jim Grosbach8213c962011-09-16 20:50:13 +00007052 }
7053 break;
7054 }
Jim Grosbach54026372011-11-10 23:17:11 +00007055 case ARM::tPOP: {
7056 bool listContainsBase;
7057 // If the register list contains any high registers, we need to use
7058 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
7059 // should have generated an error in validateInstruction().
7060 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00007061 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00007062 assert (isThumbTwo());
7063 Inst.setOpcode(ARM::t2LDMIA_UPD);
7064 // Add the base register and writeback operands.
7065 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
7066 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00007067 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00007068 }
7069 case ARM::tPUSH: {
7070 bool listContainsBase;
7071 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00007072 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00007073 assert (isThumbTwo());
7074 Inst.setOpcode(ARM::t2STMDB_UPD);
7075 // Add the base register and writeback operands.
7076 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
7077 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00007078 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00007079 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00007080 case ARM::t2MOVi: {
7081 // If we can use the 16-bit encoding and the user didn't explicitly
7082 // request the 32-bit variant, transform it here.
7083 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
Jim Grosbachc0164f82012-03-30 16:31:31 +00007084 (unsigned)Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00007085 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
7086 Inst.getOperand(4).getReg() == ARM::CPSR) ||
7087 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00007088 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
7089 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
7090 // The operands aren't in the same order for tMOVi8...
7091 MCInst TmpInst;
7092 TmpInst.setOpcode(ARM::tMOVi8);
7093 TmpInst.addOperand(Inst.getOperand(0));
7094 TmpInst.addOperand(Inst.getOperand(4));
7095 TmpInst.addOperand(Inst.getOperand(1));
7096 TmpInst.addOperand(Inst.getOperand(2));
7097 TmpInst.addOperand(Inst.getOperand(3));
7098 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00007099 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00007100 }
7101 break;
7102 }
7103 case ARM::t2MOVr: {
7104 // If we can use the 16-bit encoding and the user didn't explicitly
7105 // request the 32-bit variant, transform it here.
7106 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
7107 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7108 Inst.getOperand(2).getImm() == ARMCC::AL &&
7109 Inst.getOperand(4).getReg() == ARM::CPSR &&
7110 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
7111 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
7112 // The operands aren't the same for tMOV[S]r... (no cc_out)
7113 MCInst TmpInst;
7114 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
7115 TmpInst.addOperand(Inst.getOperand(0));
7116 TmpInst.addOperand(Inst.getOperand(1));
7117 TmpInst.addOperand(Inst.getOperand(2));
7118 TmpInst.addOperand(Inst.getOperand(3));
7119 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00007120 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00007121 }
7122 break;
7123 }
Jim Grosbach326efe52011-09-19 20:29:33 +00007124 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00007125 case ARM::t2SXTB:
7126 case ARM::t2UXTH:
7127 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00007128 // If we can use the 16-bit encoding and the user didn't explicitly
7129 // request the 32-bit variant, transform it here.
7130 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
7131 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7132 Inst.getOperand(2).getImm() == 0 &&
7133 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
7134 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00007135 unsigned NewOpc;
7136 switch (Inst.getOpcode()) {
7137 default: llvm_unreachable("Illegal opcode!");
7138 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
7139 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
7140 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
7141 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
7142 }
Jim Grosbach326efe52011-09-19 20:29:33 +00007143 // The operands aren't the same for thumb1 (no rotate operand).
7144 MCInst TmpInst;
7145 TmpInst.setOpcode(NewOpc);
7146 TmpInst.addOperand(Inst.getOperand(0));
7147 TmpInst.addOperand(Inst.getOperand(1));
7148 TmpInst.addOperand(Inst.getOperand(3));
7149 TmpInst.addOperand(Inst.getOperand(4));
7150 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00007151 return true;
Jim Grosbach326efe52011-09-19 20:29:33 +00007152 }
7153 break;
7154 }
Jim Grosbach04b5d932011-12-20 00:59:38 +00007155 case ARM::MOVsi: {
7156 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm());
7157 if (SOpc == ARM_AM::rrx) return false;
7158 if (ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()) == 0) {
7159 // Shifting by zero is accepted as a vanilla 'MOVr'
7160 MCInst TmpInst;
7161 TmpInst.setOpcode(ARM::MOVr);
7162 TmpInst.addOperand(Inst.getOperand(0));
7163 TmpInst.addOperand(Inst.getOperand(1));
7164 TmpInst.addOperand(Inst.getOperand(3));
7165 TmpInst.addOperand(Inst.getOperand(4));
7166 TmpInst.addOperand(Inst.getOperand(5));
7167 Inst = TmpInst;
7168 return true;
7169 }
7170 return false;
7171 }
Jim Grosbach8d9550b2011-12-22 18:04:04 +00007172 case ARM::ANDrsi:
7173 case ARM::ORRrsi:
7174 case ARM::EORrsi:
7175 case ARM::BICrsi:
7176 case ARM::SUBrsi:
7177 case ARM::ADDrsi: {
7178 unsigned newOpc;
7179 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(3).getImm());
7180 if (SOpc == ARM_AM::rrx) return false;
7181 switch (Inst.getOpcode()) {
Craig Topperbc219812012-02-07 02:50:20 +00007182 default: llvm_unreachable("unexpected opcode!");
Jim Grosbach8d9550b2011-12-22 18:04:04 +00007183 case ARM::ANDrsi: newOpc = ARM::ANDrr; break;
7184 case ARM::ORRrsi: newOpc = ARM::ORRrr; break;
7185 case ARM::EORrsi: newOpc = ARM::EORrr; break;
7186 case ARM::BICrsi: newOpc = ARM::BICrr; break;
7187 case ARM::SUBrsi: newOpc = ARM::SUBrr; break;
7188 case ARM::ADDrsi: newOpc = ARM::ADDrr; break;
7189 }
7190 // If the shift is by zero, use the non-shifted instruction definition.
7191 if (ARM_AM::getSORegOffset(Inst.getOperand(3).getImm()) == 0) {
7192 MCInst TmpInst;
7193 TmpInst.setOpcode(newOpc);
7194 TmpInst.addOperand(Inst.getOperand(0));
7195 TmpInst.addOperand(Inst.getOperand(1));
7196 TmpInst.addOperand(Inst.getOperand(2));
7197 TmpInst.addOperand(Inst.getOperand(4));
7198 TmpInst.addOperand(Inst.getOperand(5));
7199 TmpInst.addOperand(Inst.getOperand(6));
7200 Inst = TmpInst;
7201 return true;
7202 }
7203 return false;
7204 }
Jim Grosbach74423e32012-01-25 19:52:01 +00007205 case ARM::ITasm:
Jim Grosbach89df9962011-08-26 21:43:41 +00007206 case ARM::t2IT: {
7207 // The mask bits for all but the first condition are represented as
7208 // the low bit of the condition code value implies 't'. We currently
7209 // always have 1 implies 't', so XOR toggle the bits if the low bit
7210 // of the condition code is zero. The encoding also expects the low
7211 // bit of the condition to be encoded as bit 4 of the mask operand,
7212 // so mask that in if needed
7213 MCOperand &MO = Inst.getOperand(1);
7214 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007215 unsigned OrigMask = Mask;
7216 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00007217 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00007218 assert(Mask && TZ <= 3 && "illegal IT mask value!");
7219 for (unsigned i = 3; i != TZ; --i)
7220 Mask ^= 1 << i;
7221 } else
7222 Mask |= 0x10;
7223 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007224
7225 // Set up the IT block state according to the IT instruction we just
7226 // matched.
7227 assert(!inITBlock() && "nested IT blocks?!");
7228 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
7229 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
7230 ITState.CurPosition = 0;
7231 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00007232 break;
7233 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00007234 }
Jim Grosbach83ec8772011-11-10 23:42:14 +00007235 return false;
Jim Grosbachf8fce712011-08-11 17:35:48 +00007236}
7237
Jim Grosbach47a0d522011-08-16 20:45:50 +00007238unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
7239 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
7240 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00007241 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00007242 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00007243 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
7244 assert(MCID.hasOptionalDef() &&
7245 "optionally flag setting instruction missing optional def operand");
7246 assert(MCID.NumOperands == Inst.getNumOperands() &&
7247 "operand count mismatch!");
7248 // Find the optional-def operand (cc_out).
7249 unsigned OpNo;
7250 for (OpNo = 0;
7251 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
7252 ++OpNo)
7253 ;
7254 // If we're parsing Thumb1, reject it completely.
7255 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
7256 return Match_MnemonicFail;
7257 // If we're parsing Thumb2, which form is legal depends on whether we're
7258 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007259 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
7260 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00007261 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007262 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
7263 inITBlock())
7264 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00007265 }
Jim Grosbach194bd892011-08-16 22:20:01 +00007266 // Some high-register supporting Thumb1 encodings only allow both registers
7267 // to be from r0-r7 when in Thumb2.
7268 else if (Opc == ARM::tADDhirr && isThumbOne() &&
7269 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7270 isARMLowRegister(Inst.getOperand(2).getReg()))
7271 return Match_RequiresThumb2;
7272 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00007273 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00007274 isARMLowRegister(Inst.getOperand(0).getReg()) &&
7275 isARMLowRegister(Inst.getOperand(1).getReg()))
7276 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00007277 return Match_Success;
7278}
7279
Jim Grosbach14ce6fa2012-04-24 22:40:08 +00007280static const char *getSubtargetFeatureName(unsigned Val);
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007281bool ARMAsmParser::
7282MatchAndEmitInstruction(SMLoc IDLoc,
7283 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
7284 MCStreamer &Out) {
7285 MCInst Inst;
7286 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00007287 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00007288 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00007289 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00007290 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00007291 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00007292 // Context sensitive operand constraints aren't handled by the matcher,
7293 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00007294 if (validateInstruction(Inst, Operands)) {
7295 // Still progress the IT block, otherwise one wrong condition causes
7296 // nasty cascading errors.
7297 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00007298 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00007299 }
Jim Grosbach189610f2011-07-26 18:25:39 +00007300
Jim Grosbachf8fce712011-08-11 17:35:48 +00007301 // Some instructions need post-processing to, for example, tweak which
Jim Grosbach83ec8772011-11-10 23:42:14 +00007302 // encoding is selected. Loop on it while changes happen so the
7303 // individual transformations can chain off each other. E.g.,
7304 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
7305 while (processInstruction(Inst, Operands))
7306 ;
Jim Grosbachf8fce712011-08-11 17:35:48 +00007307
Jim Grosbacha1109882011-09-02 23:22:08 +00007308 // Only move forward at the very end so that everything in validate
7309 // and process gets a consistent answer about whether we're in an IT
7310 // block.
7311 forwardITPosition();
7312
Jim Grosbach74423e32012-01-25 19:52:01 +00007313 // ITasm is an ARM mode pseudo-instruction that just sets the ITblock and
7314 // doesn't actually encode.
7315 if (Inst.getOpcode() == ARM::ITasm)
7316 return false;
7317
Jim Grosbach42e6bd32012-01-26 23:20:15 +00007318 Inst.setLoc(IDLoc);
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007319 Out.EmitInstruction(Inst);
7320 return false;
Jim Grosbach14ce6fa2012-04-24 22:40:08 +00007321 case Match_MissingFeature: {
7322 assert(ErrorInfo && "Unknown missing feature!");
7323 // Special case the error message for the very common case where only
7324 // a single subtarget feature is missing (Thumb vs. ARM, e.g.).
7325 std::string Msg = "instruction requires:";
7326 unsigned Mask = 1;
7327 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
7328 if (ErrorInfo & Mask) {
7329 Msg += " ";
7330 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
7331 }
7332 Mask <<= 1;
7333 }
7334 return Error(IDLoc, Msg);
7335 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00007336 case Match_InvalidOperand: {
7337 SMLoc ErrorLoc = IDLoc;
7338 if (ErrorInfo != ~0U) {
7339 if (ErrorInfo >= Operands.size())
7340 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00007341
Chris Lattnere73d4f82010-10-28 21:41:58 +00007342 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
7343 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
7344 }
Jim Grosbach16c74252010-10-29 14:46:02 +00007345
Chris Lattnere73d4f82010-10-28 21:41:58 +00007346 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007347 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00007348 case Match_MnemonicFail:
Benjamin Kramer362a05a2012-04-15 17:04:27 +00007349 return Error(IDLoc, "invalid instruction",
7350 ((ARMOperand*)Operands[0])->getLocRange());
Daniel Dunbarb4129152011-02-04 17:12:23 +00007351 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00007352 // The converter function will have already emited a diagnostic.
7353 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007354 case Match_RequiresNotITBlock:
7355 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00007356 case Match_RequiresITBlock:
7357 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00007358 case Match_RequiresV6:
7359 return Error(IDLoc, "instruction variant requires ARMv6 or later");
7360 case Match_RequiresThumb2:
7361 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00007362 }
Jim Grosbach16c74252010-10-29 14:46:02 +00007363
Eric Christopherc223e2b2010-10-29 09:26:59 +00007364 llvm_unreachable("Implement any new match types added!");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007365}
7366
Jim Grosbach1355cf12011-07-26 17:10:22 +00007367/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007368bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
7369 StringRef IDVal = DirectiveID.getIdentifier();
7370 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007371 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007372 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007373 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach9a70df92011-12-07 18:04:19 +00007374 else if (IDVal == ".arm")
7375 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007376 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007377 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007378 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007379 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007380 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007381 return parseDirectiveSyntax(DirectiveID.getLoc());
Jim Grosbacha39cda72011-12-14 02:16:11 +00007382 else if (IDVal == ".unreq")
7383 return parseDirectiveUnreq(DirectiveID.getLoc());
Jason W Kimd7c9e082011-12-20 17:38:12 +00007384 else if (IDVal == ".arch")
7385 return parseDirectiveArch(DirectiveID.getLoc());
7386 else if (IDVal == ".eabi_attribute")
7387 return parseDirectiveEabiAttr(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007388 return true;
7389}
7390
Jim Grosbach1355cf12011-07-26 17:10:22 +00007391/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007392/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00007393bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007394 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7395 for (;;) {
7396 const MCExpr *Value;
7397 if (getParser().ParseExpression(Value))
7398 return true;
7399
Chris Lattneraaec2052010-01-19 19:46:13 +00007400 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007401
7402 if (getLexer().is(AsmToken::EndOfStatement))
7403 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00007404
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007405 // FIXME: Improve diagnostic.
7406 if (getLexer().isNot(AsmToken::Comma))
7407 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007408 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007409 }
7410 }
7411
Sean Callananb9a25b72010-01-19 20:27:46 +00007412 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007413 return false;
7414}
7415
Jim Grosbach1355cf12011-07-26 17:10:22 +00007416/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00007417/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00007418bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00007419 if (getLexer().isNot(AsmToken::EndOfStatement))
7420 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007421 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007422
Jim Grosbach9a70df92011-12-07 18:04:19 +00007423 if (!isThumb())
7424 SwitchMode();
7425 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
7426 return false;
7427}
7428
7429/// parseDirectiveARM
7430/// ::= .arm
7431bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
7432 if (getLexer().isNot(AsmToken::EndOfStatement))
7433 return Error(L, "unexpected token in directive");
7434 Parser.Lex();
7435
7436 if (isThumb())
7437 SwitchMode();
7438 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby515d5092009-10-15 20:48:48 +00007439 return false;
7440}
7441
Jim Grosbach1355cf12011-07-26 17:10:22 +00007442/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00007443/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00007444bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00007445 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
7446 bool isMachO = MAI.hasSubsectionsViaSymbols();
7447 StringRef Name;
Jim Grosbachde4d8392011-12-21 22:30:16 +00007448 bool needFuncName = true;
Rafael Espindola64695402011-05-16 16:17:21 +00007449
Jim Grosbachde4d8392011-12-21 22:30:16 +00007450 // Darwin asm has (optionally) function name after .thumb_func direction
Rafael Espindola64695402011-05-16 16:17:21 +00007451 // ELF doesn't
7452 if (isMachO) {
7453 const AsmToken &Tok = Parser.getTok();
Jim Grosbachde4d8392011-12-21 22:30:16 +00007454 if (Tok.isNot(AsmToken::EndOfStatement)) {
7455 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
7456 return Error(L, "unexpected token in .thumb_func directive");
7457 Name = Tok.getIdentifier();
7458 Parser.Lex(); // Consume the identifier token.
7459 needFuncName = false;
7460 }
Rafael Espindola64695402011-05-16 16:17:21 +00007461 }
7462
Jim Grosbachde4d8392011-12-21 22:30:16 +00007463 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby515d5092009-10-15 20:48:48 +00007464 return Error(L, "unexpected token in directive");
Jim Grosbachde4d8392011-12-21 22:30:16 +00007465
7466 // Eat the end of statement and any blank lines that follow.
7467 while (getLexer().is(AsmToken::EndOfStatement))
7468 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007469
Rafael Espindola64695402011-05-16 16:17:21 +00007470 // FIXME: assuming function name will be the line following .thumb_func
Jim Grosbachde4d8392011-12-21 22:30:16 +00007471 // We really should be checking the next symbol definition even if there's
7472 // stuff in between.
7473 if (needFuncName) {
Jim Grosbachd475f862011-11-10 20:48:53 +00007474 Name = Parser.getTok().getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00007475 }
7476
Jim Grosbach642fc9c2010-11-05 22:33:53 +00007477 // Mark symbol as a thumb symbol.
7478 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
7479 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00007480 return false;
7481}
7482
Jim Grosbach1355cf12011-07-26 17:10:22 +00007483/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00007484/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00007485bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00007486 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00007487 if (Tok.isNot(AsmToken::Identifier))
7488 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00007489 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00007490 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00007491 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00007492 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00007493 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00007494 else
7495 return Error(L, "unrecognized syntax mode in .syntax directive");
7496
7497 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00007498 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007499 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007500
7501 // TODO tell the MC streamer the mode
7502 // getParser().getStreamer().Emit???();
7503 return false;
7504}
7505
Jim Grosbach1355cf12011-07-26 17:10:22 +00007506/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00007507/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00007508bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00007509 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00007510 if (Tok.isNot(AsmToken::Integer))
7511 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00007512 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00007513 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00007514 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00007515 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00007516 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007517 else
7518 return Error(L, "invalid operand to .code directive");
7519
7520 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00007521 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007522 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007523
Evan Cheng32869202011-07-08 22:36:29 +00007524 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00007525 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00007526 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00007527 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00007528 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00007529 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00007530 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00007531 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00007532 }
Jim Grosbach2a301702010-11-05 22:40:53 +00007533
Kevin Enderby515d5092009-10-15 20:48:48 +00007534 return false;
7535}
7536
Jim Grosbacha39cda72011-12-14 02:16:11 +00007537/// parseDirectiveReq
7538/// ::= name .req registername
7539bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
7540 Parser.Lex(); // Eat the '.req' token.
7541 unsigned Reg;
7542 SMLoc SRegLoc, ERegLoc;
7543 if (ParseRegister(Reg, SRegLoc, ERegLoc)) {
7544 Parser.EatToEndOfStatement();
7545 return Error(SRegLoc, "register name expected");
7546 }
7547
7548 // Shouldn't be anything else.
7549 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
7550 Parser.EatToEndOfStatement();
7551 return Error(Parser.getTok().getLoc(),
7552 "unexpected input in .req directive.");
7553 }
7554
7555 Parser.Lex(); // Consume the EndOfStatement
7556
7557 if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg)
7558 return Error(SRegLoc, "redefinition of '" + Name +
7559 "' does not match original.");
7560
7561 return false;
7562}
7563
7564/// parseDirectiveUneq
7565/// ::= .unreq registername
7566bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
7567 if (Parser.getTok().isNot(AsmToken::Identifier)) {
7568 Parser.EatToEndOfStatement();
7569 return Error(L, "unexpected input in .unreq directive.");
7570 }
7571 RegisterReqs.erase(Parser.getTok().getIdentifier());
7572 Parser.Lex(); // Eat the identifier.
7573 return false;
7574}
7575
Jason W Kimd7c9e082011-12-20 17:38:12 +00007576/// parseDirectiveArch
7577/// ::= .arch token
7578bool ARMAsmParser::parseDirectiveArch(SMLoc L) {
7579 return true;
7580}
7581
7582/// parseDirectiveEabiAttr
7583/// ::= .eabi_attribute int, int
7584bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
7585 return true;
7586}
7587
Sean Callanan90b70972010-04-07 20:29:34 +00007588extern "C" void LLVMInitializeARMAsmLexer();
7589
Kevin Enderby9c41fa82009-10-30 22:55:57 +00007590/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007591extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00007592 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
7593 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00007594 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007595}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00007596
Chris Lattner0692ee62010-09-06 19:11:01 +00007597#define GET_REGISTER_MATCHER
7598#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00007599#include "ARMGenAsmMatcher.inc"