blob: 44977201abd4a7d43a1c6a213392c43d368b7fc2 [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,
Jim Grosbach70c9bf32012-06-22 23:56:48 +0000239 Match_RequiresThumb2,
240#define GET_OPERAND_DIAGNOSTIC_TYPES
241#include "ARMGenAsmMatcher.inc"
242
Jim Grosbach47a0d522011-08-16 20:45:50 +0000243 };
244
Evan Chengffc0e732011-07-09 05:47:46 +0000245 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng94b95502011-07-26 00:24:13 +0000246 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Chengebdeeab2011-07-08 01:53:10 +0000247 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng32869202011-07-08 22:36:29 +0000248
Jim Grosbach28f08c92012-03-05 19:33:30 +0000249 // Cache the MCRegisterInfo.
250 MRI = &getContext().getRegisterInfo();
251
Evan Chengebdeeab2011-07-08 01:53:10 +0000252 // Initialize the set of available features.
Evan Chengffc0e732011-07-09 05:47:46 +0000253 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000254
255 // Not in an ITBlock to start with.
256 ITState.CurPosition = ~0U;
Evan Chengebdeeab2011-07-08 01:53:10 +0000257 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000258
Jim Grosbach1355cf12011-07-26 17:10:22 +0000259 // Implementation of the MCTargetAsmParser interface:
260 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
261 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbach189610f2011-07-26 18:25:39 +0000262 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000263 bool ParseDirective(AsmToken DirectiveID);
264
Jim Grosbach47a0d522011-08-16 20:45:50 +0000265 unsigned checkTargetMatchPredicate(MCInst &Inst);
266
Jim Grosbach1355cf12011-07-26 17:10:22 +0000267 bool MatchAndEmitInstruction(SMLoc IDLoc,
268 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
269 MCStreamer &Out);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000270};
Jim Grosbach16c74252010-10-29 14:46:02 +0000271} // end anonymous namespace
272
Chris Lattner3a697562010-10-28 17:20:03 +0000273namespace {
274
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000275/// ARMOperand - Instances of this class represent a parsed ARM machine
276/// instruction.
Bill Wendling146018f2010-11-06 21:42:12 +0000277class ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000278 enum KindTy {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000279 k_CondCode,
280 k_CCOut,
281 k_ITCondMask,
282 k_CoprocNum,
283 k_CoprocReg,
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000284 k_CoprocOption,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000285 k_Immediate,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000286 k_MemBarrierOpt,
287 k_Memory,
288 k_PostIndexRegister,
289 k_MSRMask,
290 k_ProcIFlags,
Jim Grosbach460a9052011-10-07 23:56:00 +0000291 k_VectorIndex,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000292 k_Register,
293 k_RegisterList,
294 k_DPRRegisterList,
295 k_SPRRegisterList,
Jim Grosbach862019c2011-10-18 23:02:30 +0000296 k_VectorList,
Jim Grosbach98b05a52011-11-30 01:09:44 +0000297 k_VectorListAllLanes,
Jim Grosbach7636bf62011-12-02 00:35:16 +0000298 k_VectorListIndexed,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000299 k_ShiftedRegister,
300 k_ShiftedImmediate,
301 k_ShifterImmediate,
302 k_RotateImmediate,
303 k_BitfieldDescriptor,
304 k_Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000305 } Kind;
306
Sean Callanan76264762010-04-02 22:27:05 +0000307 SMLoc StartLoc, EndLoc;
Bill Wendling24d22d22010-11-18 21:50:54 +0000308 SmallVector<unsigned, 8> Registers;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000309
310 union {
311 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000312 ARMCC::CondCodes Val;
313 } CC;
314
315 struct {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000316 unsigned Val;
317 } Cop;
318
319 struct {
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000320 unsigned Val;
321 } CoprocOption;
322
323 struct {
Jim Grosbach89df9962011-08-26 21:43:41 +0000324 unsigned Mask:4;
325 } ITMask;
326
327 struct {
328 ARM_MB::MemBOpt Val;
329 } MBOpt;
330
331 struct {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000332 ARM_PROC::IFlags Val;
333 } IFlags;
334
335 struct {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000336 unsigned Val;
337 } MMask;
338
339 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000340 const char *Data;
341 unsigned Length;
342 } Tok;
343
344 struct {
345 unsigned RegNum;
346 } Reg;
347
Jim Grosbach862019c2011-10-18 23:02:30 +0000348 // A vector register list is a sequential list of 1 to 4 registers.
349 struct {
350 unsigned RegNum;
351 unsigned Count;
Jim Grosbach7636bf62011-12-02 00:35:16 +0000352 unsigned LaneIndex;
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +0000353 bool isDoubleSpaced;
Jim Grosbach862019c2011-10-18 23:02:30 +0000354 } VectorList;
355
Bill Wendling8155e5b2010-11-06 22:19:43 +0000356 struct {
Jim Grosbach460a9052011-10-07 23:56:00 +0000357 unsigned Val;
358 } VectorIndex;
359
360 struct {
Kevin Enderbycfe07242009-10-13 22:19:02 +0000361 const MCExpr *Val;
362 } Imm;
Jim Grosbach16c74252010-10-29 14:46:02 +0000363
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +0000364 /// Combined record for all forms of ARM address expressions.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000365 struct {
366 unsigned BaseRegNum;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000367 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
368 // was specified.
369 const MCConstantExpr *OffsetImm; // Offset immediate value
370 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
371 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbach57dcb852011-10-11 17:29:55 +0000372 unsigned ShiftImm; // shift for OffsetReg.
373 unsigned Alignment; // 0 = no alignment specified
Jim Grosbacheeaf1c12011-12-19 18:31:43 +0000374 // n = alignment in bytes (2, 4, 8, 16, or 32)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000375 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbache53c87b2011-10-11 15:59:20 +0000376 } Memory;
Owen Anderson00828302011-03-18 22:50:18 +0000377
378 struct {
Jim Grosbach7ce05792011-08-03 23:50:40 +0000379 unsigned RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000380 bool isAdd;
381 ARM_AM::ShiftOpc ShiftTy;
382 unsigned ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000383 } PostIdxReg;
384
385 struct {
Jim Grosbach580f4a92011-07-25 22:20:28 +0000386 bool isASR;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000387 unsigned Imm;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000388 } ShifterImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000389 struct {
390 ARM_AM::ShiftOpc ShiftTy;
391 unsigned SrcReg;
392 unsigned ShiftReg;
393 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000394 } RegShiftedReg;
Owen Anderson92a20222011-07-21 18:54:16 +0000395 struct {
396 ARM_AM::ShiftOpc ShiftTy;
397 unsigned SrcReg;
398 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000399 } RegShiftedImm;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000400 struct {
401 unsigned Imm;
402 } RotImm;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000403 struct {
404 unsigned LSB;
405 unsigned Width;
406 } Bitfield;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000407 };
Jim Grosbach16c74252010-10-29 14:46:02 +0000408
Bill Wendling146018f2010-11-06 21:42:12 +0000409 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
410public:
Sean Callanan76264762010-04-02 22:27:05 +0000411 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
412 Kind = o.Kind;
413 StartLoc = o.StartLoc;
414 EndLoc = o.EndLoc;
415 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000416 case k_CondCode:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000417 CC = o.CC;
418 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000419 case k_ITCondMask:
Jim Grosbach89df9962011-08-26 21:43:41 +0000420 ITMask = o.ITMask;
421 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000422 case k_Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000423 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000424 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000425 case k_CCOut:
426 case k_Register:
Sean Callanan76264762010-04-02 22:27:05 +0000427 Reg = o.Reg;
428 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000429 case k_RegisterList:
430 case k_DPRRegisterList:
431 case k_SPRRegisterList:
Bill Wendling24d22d22010-11-18 21:50:54 +0000432 Registers = o.Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000433 break;
Jim Grosbach862019c2011-10-18 23:02:30 +0000434 case k_VectorList:
Jim Grosbach98b05a52011-11-30 01:09:44 +0000435 case k_VectorListAllLanes:
Jim Grosbach7636bf62011-12-02 00:35:16 +0000436 case k_VectorListIndexed:
Jim Grosbach862019c2011-10-18 23:02:30 +0000437 VectorList = o.VectorList;
438 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000439 case k_CoprocNum:
440 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000441 Cop = o.Cop;
442 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000443 case k_CoprocOption:
444 CoprocOption = o.CoprocOption;
445 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000446 case k_Immediate:
Sean Callanan76264762010-04-02 22:27:05 +0000447 Imm = o.Imm;
448 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000449 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000450 MBOpt = o.MBOpt;
451 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000452 case k_Memory:
Jim Grosbache53c87b2011-10-11 15:59:20 +0000453 Memory = o.Memory;
Sean Callanan76264762010-04-02 22:27:05 +0000454 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000455 case k_PostIndexRegister:
Jim Grosbach7ce05792011-08-03 23:50:40 +0000456 PostIdxReg = o.PostIdxReg;
457 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000458 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000459 MMask = o.MMask;
460 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000461 case k_ProcIFlags:
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000462 IFlags = o.IFlags;
Owen Anderson00828302011-03-18 22:50:18 +0000463 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000464 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +0000465 ShifterImm = o.ShifterImm;
Owen Anderson00828302011-03-18 22:50:18 +0000466 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000467 case k_ShiftedRegister:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000468 RegShiftedReg = o.RegShiftedReg;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000469 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000470 case k_ShiftedImmediate:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000471 RegShiftedImm = o.RegShiftedImm;
Owen Anderson92a20222011-07-21 18:54:16 +0000472 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000473 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000474 RotImm = o.RotImm;
475 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000476 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000477 Bitfield = o.Bitfield;
478 break;
Jim Grosbach460a9052011-10-07 23:56:00 +0000479 case k_VectorIndex:
480 VectorIndex = o.VectorIndex;
481 break;
Sean Callanan76264762010-04-02 22:27:05 +0000482 }
483 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000484
Sean Callanan76264762010-04-02 22:27:05 +0000485 /// getStartLoc - Get the location of the first token of this operand.
486 SMLoc getStartLoc() const { return StartLoc; }
487 /// getEndLoc - Get the location of the last token of this operand.
488 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000489
Benjamin Kramer362a05a2012-04-15 17:04:27 +0000490 SMRange getLocRange() const { return SMRange(StartLoc, EndLoc); }
491
Daniel Dunbar8462b302010-08-11 06:36:53 +0000492 ARMCC::CondCodes getCondCode() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000493 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000494 return CC.Val;
495 }
496
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000497 unsigned getCoproc() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000498 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000499 return Cop.Val;
500 }
501
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000502 StringRef getToken() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000503 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000504 return StringRef(Tok.Data, Tok.Length);
505 }
506
507 unsigned getReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000508 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling7729e062010-11-09 22:44:22 +0000509 return Reg.RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000510 }
511
Bill Wendling5fa22a12010-11-09 23:28:44 +0000512 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000513 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
514 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling24d22d22010-11-18 21:50:54 +0000515 return Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000516 }
517
Kevin Enderbycfe07242009-10-13 22:19:02 +0000518 const MCExpr *getImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000519 assert(isImm() && "Invalid access!");
Kevin Enderbycfe07242009-10-13 22:19:02 +0000520 return Imm.Val;
521 }
522
Jim Grosbach460a9052011-10-07 23:56:00 +0000523 unsigned getVectorIndex() const {
524 assert(Kind == k_VectorIndex && "Invalid access!");
525 return VectorIndex.Val;
526 }
527
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000528 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000529 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000530 return MBOpt.Val;
531 }
532
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000533 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000534 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000535 return IFlags.Val;
536 }
537
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000538 unsigned getMSRMask() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000539 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000540 return MMask.Val;
541 }
542
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000543 bool isCoprocNum() const { return Kind == k_CoprocNum; }
544 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000545 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000546 bool isCondCode() const { return Kind == k_CondCode; }
547 bool isCCOut() const { return Kind == k_CCOut; }
548 bool isITMask() const { return Kind == k_ITCondMask; }
549 bool isITCondCode() const { return Kind == k_CondCode; }
550 bool isImm() const { return Kind == k_Immediate; }
Jim Grosbach51222d12012-01-20 18:09:51 +0000551 bool isFPImm() const {
552 if (!isImm()) return false;
553 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
554 if (!CE) return false;
555 int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
556 return Val != -1;
557 }
Jim Grosbach4050bc42011-12-22 22:19:05 +0000558 bool isFBits16() const {
559 if (!isImm()) return false;
560 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
561 if (!CE) return false;
562 int64_t Value = CE->getValue();
563 return Value >= 0 && Value <= 16;
564 }
565 bool isFBits32() const {
566 if (!isImm()) return false;
567 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
568 if (!CE) return false;
569 int64_t Value = CE->getValue();
570 return Value >= 1 && Value <= 32;
571 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000572 bool isImm8s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000573 if (!isImm()) return false;
Jim Grosbacha77295d2011-09-08 22:07:06 +0000574 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
575 if (!CE) return false;
576 int64_t Value = CE->getValue();
577 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
578 }
Jim Grosbach72f39f82011-08-24 21:22:15 +0000579 bool isImm0_1020s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000580 if (!isImm()) return false;
Jim Grosbach72f39f82011-08-24 21:22:15 +0000581 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
582 if (!CE) return false;
583 int64_t Value = CE->getValue();
584 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
585 }
586 bool isImm0_508s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000587 if (!isImm()) return false;
Jim Grosbach72f39f82011-08-24 21:22:15 +0000588 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
589 if (!CE) return false;
590 int64_t Value = CE->getValue();
591 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
592 }
Jim Grosbach4e53fe82012-04-05 20:57:13 +0000593 bool isImm0_508s4Neg() const {
594 if (!isImm()) return false;
595 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
596 if (!CE) return false;
597 int64_t Value = -CE->getValue();
598 // explicitly exclude zero. we want that to use the normal 0_508 version.
599 return ((Value & 3) == 0) && Value > 0 && Value <= 508;
600 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000601 bool isImm0_255() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000602 if (!isImm()) return false;
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000603 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
604 if (!CE) return false;
605 int64_t Value = CE->getValue();
606 return Value >= 0 && Value < 256;
607 }
Jim Grosbach4e53fe82012-04-05 20:57:13 +0000608 bool isImm0_4095() const {
609 if (!isImm()) return false;
610 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
611 if (!CE) return false;
612 int64_t Value = CE->getValue();
613 return Value >= 0 && Value < 4096;
614 }
615 bool isImm0_4095Neg() const {
616 if (!isImm()) return false;
617 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
618 if (!CE) return false;
619 int64_t Value = -CE->getValue();
620 return Value > 0 && Value < 4096;
621 }
Jim Grosbach587f5062011-12-02 23:34:39 +0000622 bool isImm0_1() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000623 if (!isImm()) return false;
Jim Grosbach587f5062011-12-02 23:34:39 +0000624 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
625 if (!CE) return false;
626 int64_t Value = CE->getValue();
627 return Value >= 0 && Value < 2;
628 }
629 bool isImm0_3() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000630 if (!isImm()) return false;
Jim Grosbach587f5062011-12-02 23:34:39 +0000631 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
632 if (!CE) return false;
633 int64_t Value = CE->getValue();
634 return Value >= 0 && Value < 4;
635 }
Jim Grosbach83ab0702011-07-13 22:01:08 +0000636 bool isImm0_7() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000637 if (!isImm()) return false;
Jim Grosbach83ab0702011-07-13 22:01:08 +0000638 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
639 if (!CE) return false;
640 int64_t Value = CE->getValue();
641 return Value >= 0 && Value < 8;
642 }
643 bool isImm0_15() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000644 if (!isImm()) return false;
Jim Grosbach83ab0702011-07-13 22:01:08 +0000645 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
646 if (!CE) return false;
647 int64_t Value = CE->getValue();
648 return Value >= 0 && Value < 16;
649 }
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000650 bool isImm0_31() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000651 if (!isImm()) return false;
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000652 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
653 if (!CE) return false;
654 int64_t Value = CE->getValue();
655 return Value >= 0 && Value < 32;
656 }
Jim Grosbach730fe6c2011-12-08 01:30:04 +0000657 bool isImm0_63() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000658 if (!isImm()) return false;
Jim Grosbach730fe6c2011-12-08 01:30:04 +0000659 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
660 if (!CE) return false;
661 int64_t Value = CE->getValue();
662 return Value >= 0 && Value < 64;
663 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000664 bool isImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000665 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000666 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
667 if (!CE) return false;
668 int64_t Value = CE->getValue();
669 return Value == 8;
670 }
671 bool isImm16() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000672 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000673 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
674 if (!CE) return false;
675 int64_t Value = CE->getValue();
676 return Value == 16;
677 }
678 bool isImm32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000679 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000680 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
681 if (!CE) return false;
682 int64_t Value = CE->getValue();
683 return Value == 32;
684 }
Jim Grosbach6b044c22011-12-08 22:06:06 +0000685 bool isShrImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000686 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000687 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
688 if (!CE) return false;
689 int64_t Value = CE->getValue();
690 return Value > 0 && Value <= 8;
691 }
692 bool isShrImm16() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000693 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000694 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
695 if (!CE) return false;
696 int64_t Value = CE->getValue();
697 return Value > 0 && Value <= 16;
698 }
699 bool isShrImm32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000700 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000701 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
702 if (!CE) return false;
703 int64_t Value = CE->getValue();
704 return Value > 0 && Value <= 32;
705 }
706 bool isShrImm64() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000707 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000708 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
709 if (!CE) return false;
710 int64_t Value = CE->getValue();
711 return Value > 0 && Value <= 64;
712 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000713 bool isImm1_7() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000714 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000715 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
716 if (!CE) return false;
717 int64_t Value = CE->getValue();
718 return Value > 0 && Value < 8;
719 }
720 bool isImm1_15() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000721 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000722 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
723 if (!CE) return false;
724 int64_t Value = CE->getValue();
725 return Value > 0 && Value < 16;
726 }
727 bool isImm1_31() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000728 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000729 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
730 if (!CE) return false;
731 int64_t Value = CE->getValue();
732 return Value > 0 && Value < 32;
733 }
Jim Grosbachf4943352011-07-25 23:09:14 +0000734 bool isImm1_16() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000735 if (!isImm()) return false;
Jim Grosbachf4943352011-07-25 23:09:14 +0000736 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
737 if (!CE) return false;
738 int64_t Value = CE->getValue();
739 return Value > 0 && Value < 17;
740 }
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000741 bool isImm1_32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000742 if (!isImm()) return false;
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000743 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
744 if (!CE) return false;
745 int64_t Value = CE->getValue();
746 return Value > 0 && Value < 33;
747 }
Jim Grosbachee10ff82011-11-10 19:18:01 +0000748 bool isImm0_32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000749 if (!isImm()) return false;
Jim Grosbachee10ff82011-11-10 19:18:01 +0000750 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
751 if (!CE) return false;
752 int64_t Value = CE->getValue();
753 return Value >= 0 && Value < 33;
754 }
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000755 bool isImm0_65535() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000756 if (!isImm()) return false;
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000757 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
758 if (!CE) return false;
759 int64_t Value = CE->getValue();
760 return Value >= 0 && Value < 65536;
761 }
Jim Grosbachffa32252011-07-19 19:13:28 +0000762 bool isImm0_65535Expr() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000763 if (!isImm()) return false;
Jim Grosbachffa32252011-07-19 19:13:28 +0000764 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
765 // If it's not a constant expression, it'll generate a fixup and be
766 // handled later.
767 if (!CE) return true;
768 int64_t Value = CE->getValue();
769 return Value >= 0 && Value < 65536;
770 }
Jim Grosbached838482011-07-26 16:24:27 +0000771 bool isImm24bit() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000772 if (!isImm()) return false;
Jim Grosbached838482011-07-26 16:24:27 +0000773 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
774 if (!CE) return false;
775 int64_t Value = CE->getValue();
776 return Value >= 0 && Value <= 0xffffff;
777 }
Jim Grosbach70939ee2011-08-17 21:51:27 +0000778 bool isImmThumbSR() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000779 if (!isImm()) return false;
Jim Grosbach70939ee2011-08-17 21:51:27 +0000780 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
781 if (!CE) return false;
782 int64_t Value = CE->getValue();
783 return Value > 0 && Value < 33;
784 }
Jim Grosbachf6c05252011-07-21 17:23:04 +0000785 bool isPKHLSLImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000786 if (!isImm()) return false;
Jim Grosbachf6c05252011-07-21 17:23:04 +0000787 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
788 if (!CE) return false;
789 int64_t Value = CE->getValue();
790 return Value >= 0 && Value < 32;
791 }
792 bool isPKHASRImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000793 if (!isImm()) return false;
Jim Grosbachf6c05252011-07-21 17:23:04 +0000794 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
795 if (!CE) return false;
796 int64_t Value = CE->getValue();
797 return Value > 0 && Value <= 32;
798 }
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000799 bool isARMSOImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000800 if (!isImm()) return false;
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000801 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
802 if (!CE) return false;
803 int64_t Value = CE->getValue();
804 return ARM_AM::getSOImmVal(Value) != -1;
805 }
Jim Grosbache70ec842011-10-28 22:50:54 +0000806 bool isARMSOImmNot() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000807 if (!isImm()) return false;
Jim Grosbache70ec842011-10-28 22:50:54 +0000808 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
809 if (!CE) return false;
810 int64_t Value = CE->getValue();
811 return ARM_AM::getSOImmVal(~Value) != -1;
812 }
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000813 bool isARMSOImmNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000814 if (!isImm()) return false;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000815 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
816 if (!CE) return false;
817 int64_t Value = CE->getValue();
Jim Grosbachad353c62012-03-30 19:59:02 +0000818 // Only use this when not representable as a plain so_imm.
819 return ARM_AM::getSOImmVal(Value) == -1 &&
820 ARM_AM::getSOImmVal(-Value) != -1;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000821 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000822 bool isT2SOImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000823 if (!isImm()) return false;
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000824 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
825 if (!CE) return false;
826 int64_t Value = CE->getValue();
827 return ARM_AM::getT2SOImmVal(Value) != -1;
828 }
Jim Grosbach89a63372011-10-28 22:36:30 +0000829 bool isT2SOImmNot() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000830 if (!isImm()) return false;
Jim Grosbach89a63372011-10-28 22:36:30 +0000831 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
832 if (!CE) return false;
833 int64_t Value = CE->getValue();
834 return ARM_AM::getT2SOImmVal(~Value) != -1;
835 }
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000836 bool isT2SOImmNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000837 if (!isImm()) return false;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000838 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
839 if (!CE) return false;
840 int64_t Value = CE->getValue();
Jim Grosbachad353c62012-03-30 19:59:02 +0000841 // Only use this when not representable as a plain so_imm.
842 return ARM_AM::getT2SOImmVal(Value) == -1 &&
843 ARM_AM::getT2SOImmVal(-Value) != -1;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000844 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000845 bool isSetEndImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000846 if (!isImm()) return false;
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000847 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
848 if (!CE) return false;
849 int64_t Value = CE->getValue();
850 return Value == 1 || Value == 0;
851 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000852 bool isReg() const { return Kind == k_Register; }
853 bool isRegList() const { return Kind == k_RegisterList; }
854 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
855 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
856 bool isToken() const { return Kind == k_Token; }
857 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
858 bool isMemory() const { return Kind == k_Memory; }
859 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
860 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
861 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
862 bool isRotImm() const { return Kind == k_RotateImmediate; }
863 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
864 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000865 bool isPostIdxReg() const {
Jim Grosbach430052b2011-11-14 17:52:47 +0000866 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000867 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000868 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000869 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000870 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000871 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000872 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
873 (alignOK || Memory.Alignment == 0);
874 }
Jim Grosbach0b4c6732012-01-18 22:46:46 +0000875 bool isMemPCRelImm12() const {
876 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
877 return false;
878 // Base register must be PC.
879 if (Memory.BaseRegNum != ARM::PC)
880 return false;
881 // Immediate offset in range [-4095, 4095].
882 if (!Memory.OffsetImm) return true;
883 int64_t Val = Memory.OffsetImm->getValue();
884 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
885 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000886 bool isAlignedMemory() const {
887 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000888 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000889 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000890 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000891 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000892 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000893 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000894 if (!Memory.OffsetImm) return true;
895 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000896 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000897 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000898 bool isAM2OffsetImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000899 if (!isImm()) return false;
Jim Grosbach039c2e12011-08-04 23:01:30 +0000900 // Immediate offset in range [-4095, 4095].
901 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
902 if (!CE) return false;
903 int64_t Val = CE->getValue();
904 return Val > -4096 && Val < 4096;
905 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000906 bool isAddrMode3() const {
Jim Grosbach2f196742011-12-19 23:06:24 +0000907 // If we have an immediate that's not a constant, treat it as a label
908 // reference needing a fixup. If it is a constant, it's something else
909 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000910 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach2f196742011-12-19 23:06:24 +0000911 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000912 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000913 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000914 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000915 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000916 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000917 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000918 if (!Memory.OffsetImm) return true;
919 int64_t Val = Memory.OffsetImm->getValue();
Silviu Barangaca3cd412012-05-11 09:10:54 +0000920 // The #-0 offset is encoded as INT32_MIN, and we have to check
921 // for this too.
922 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000923 }
924 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000925 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000926 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000927 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000928 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
929 // Immediate offset in range [-255, 255].
930 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
931 if (!CE) return false;
932 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000933 // Special case, #-0 is INT32_MIN.
934 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000935 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000936 bool isAddrMode5() const {
Jim Grosbach681460f2011-11-01 01:24:45 +0000937 // If we have an immediate that's not a constant, treat it as a label
938 // reference needing a fixup. If it is a constant, it's something else
939 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000940 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach681460f2011-11-01 01:24:45 +0000941 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000942 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000943 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000944 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000945 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000946 if (!Memory.OffsetImm) return true;
947 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000948 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbach681460f2011-11-01 01:24:45 +0000949 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000950 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000951 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000952 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000953 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000954 return false;
955 return true;
956 }
957 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000958 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000959 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
960 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000961 return false;
962 return true;
963 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000964 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000965 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000966 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000967 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000968 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000969 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000970 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
971 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000972 return false;
973 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000974 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000975 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000976 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000977 return false;
978 return true;
979 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000980 bool isMemThumbRR() const {
981 // Thumb reg+reg addressing is simple. Just two registers, a base and
982 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000983 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000984 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000985 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000986 return isARMLowRegister(Memory.BaseRegNum) &&
987 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000988 }
989 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000990 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000991 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000992 return false;
993 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000994 if (!Memory.OffsetImm) return true;
995 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000996 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
997 }
Jim Grosbach38466302011-08-19 18:55:51 +0000998 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000999 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +00001000 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +00001001 return false;
1002 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001003 if (!Memory.OffsetImm) return true;
1004 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +00001005 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
1006 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001007 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +00001008 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +00001009 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001010 return false;
1011 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001012 if (!Memory.OffsetImm) return true;
1013 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001014 return Val >= 0 && Val <= 31;
1015 }
Jim Grosbachecd85892011-08-19 18:13:48 +00001016 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001017 if (!isMemory() || Memory.OffsetRegNum != 0 ||
1018 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +00001019 return false;
1020 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001021 if (!Memory.OffsetImm) return true;
1022 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +00001023 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001024 }
Jim Grosbacha77295d2011-09-08 22:07:06 +00001025 bool isMemImm8s4Offset() const {
Jim Grosbach2f196742011-12-19 23:06:24 +00001026 // If we have an immediate that's not a constant, treat it as a label
1027 // reference needing a fixup. If it is a constant, it's something else
1028 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001029 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach2f196742011-12-19 23:06:24 +00001030 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +00001031 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +00001032 return false;
1033 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001034 if (!Memory.OffsetImm) return true;
1035 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +00001036 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
1037 }
Jim Grosbachb6aed502011-09-09 18:37:27 +00001038 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001039 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +00001040 return false;
1041 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001042 if (!Memory.OffsetImm) return true;
1043 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +00001044 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
1045 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001046 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001047 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001048 return false;
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001049 // Base reg of PC isn't allowed for these encodings.
1050 if (Memory.BaseRegNum == ARM::PC) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001051 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001052 if (!Memory.OffsetImm) return true;
1053 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +00001054 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001055 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001056 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001057 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001058 return false;
1059 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001060 if (!Memory.OffsetImm) return true;
1061 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001062 return Val >= 0 && Val < 256;
1063 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001064 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001065 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001066 return false;
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001067 // Base reg of PC isn't allowed for these encodings.
1068 if (Memory.BaseRegNum == ARM::PC) return false;
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001069 // Immediate offset in range [-255, -1].
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001070 if (!Memory.OffsetImm) return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001071 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001072 return (Val == INT32_MIN) || (Val > -256 && Val < 0);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001073 }
1074 bool isMemUImm12Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001075 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001076 return false;
1077 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001078 if (!Memory.OffsetImm) return true;
1079 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001080 return (Val >= 0 && Val < 4096);
1081 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001082 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +00001083 // If we have an immediate that's not a constant, treat it as a label
1084 // reference needing a fixup. If it is a constant, it's something else
1085 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001086 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +00001087 return true;
1088
Jim Grosbach57dcb852011-10-11 17:29:55 +00001089 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001090 return false;
1091 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001092 if (!Memory.OffsetImm) return true;
1093 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +00001094 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001095 }
1096 bool isPostIdxImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001097 if (!isImm()) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001098 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1099 if (!CE) return false;
1100 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +00001101 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001102 }
Jim Grosbach2bd01182011-10-11 21:55:36 +00001103 bool isPostIdxImm8s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001104 if (!isImm()) return false;
Jim Grosbach2bd01182011-10-11 21:55:36 +00001105 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1106 if (!CE) return false;
1107 int64_t Val = CE->getValue();
1108 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1109 (Val == INT32_MIN);
1110 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001111
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001112 bool isMSRMask() const { return Kind == k_MSRMask; }
1113 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001114
Jim Grosbach0e387b22011-10-17 22:26:03 +00001115 // NEON operands.
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001116 bool isSingleSpacedVectorList() const {
1117 return Kind == k_VectorList && !VectorList.isDoubleSpaced;
1118 }
1119 bool isDoubleSpacedVectorList() const {
1120 return Kind == k_VectorList && VectorList.isDoubleSpaced;
1121 }
Jim Grosbach862019c2011-10-18 23:02:30 +00001122 bool isVecListOneD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001123 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach862019c2011-10-18 23:02:30 +00001124 return VectorList.Count == 1;
1125 }
1126
Jim Grosbach28f08c92012-03-05 19:33:30 +00001127 bool isVecListDPair() const {
1128 if (!isSingleSpacedVectorList()) return false;
1129 return (ARMMCRegisterClasses[ARM::DPairRegClassID]
1130 .contains(VectorList.RegNum));
1131 }
1132
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001133 bool isVecListThreeD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001134 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001135 return VectorList.Count == 3;
1136 }
1137
Jim Grosbachb6310312011-10-21 20:35:01 +00001138 bool isVecListFourD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001139 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachb6310312011-10-21 20:35:01 +00001140 return VectorList.Count == 4;
1141 }
1142
Jim Grosbachc3384c92012-03-05 21:43:40 +00001143 bool isVecListDPairSpaced() const {
Kevin Enderby9f2e1602012-03-20 17:41:51 +00001144 if (isSingleSpacedVectorList()) return false;
Jim Grosbachc3384c92012-03-05 21:43:40 +00001145 return (ARMMCRegisterClasses[ARM::DPairSpcRegClassID]
1146 .contains(VectorList.RegNum));
1147 }
1148
Jim Grosbachc387fc62012-01-23 23:20:46 +00001149 bool isVecListThreeQ() const {
1150 if (!isDoubleSpacedVectorList()) return false;
1151 return VectorList.Count == 3;
1152 }
1153
Jim Grosbach7945ead2012-01-24 00:43:12 +00001154 bool isVecListFourQ() const {
1155 if (!isDoubleSpacedVectorList()) return false;
1156 return VectorList.Count == 4;
1157 }
1158
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001159 bool isSingleSpacedVectorAllLanes() const {
1160 return Kind == k_VectorListAllLanes && !VectorList.isDoubleSpaced;
1161 }
1162 bool isDoubleSpacedVectorAllLanes() const {
1163 return Kind == k_VectorListAllLanes && VectorList.isDoubleSpaced;
1164 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00001165 bool isVecListOneDAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001166 if (!isSingleSpacedVectorAllLanes()) return false;
Jim Grosbach98b05a52011-11-30 01:09:44 +00001167 return VectorList.Count == 1;
1168 }
1169
Jim Grosbachc0fc4502012-03-06 22:01:44 +00001170 bool isVecListDPairAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001171 if (!isSingleSpacedVectorAllLanes()) return false;
Jim Grosbachc0fc4502012-03-06 22:01:44 +00001172 return (ARMMCRegisterClasses[ARM::DPairRegClassID]
1173 .contains(VectorList.RegNum));
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001174 }
1175
Jim Grosbach4d0983a2012-03-06 23:10:38 +00001176 bool isVecListDPairSpacedAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001177 if (!isDoubleSpacedVectorAllLanes()) return false;
Jim Grosbach13af2222011-11-30 18:21:25 +00001178 return VectorList.Count == 2;
1179 }
1180
Jim Grosbach5e59f7e2012-01-24 23:47:04 +00001181 bool isVecListThreeDAllLanes() const {
1182 if (!isSingleSpacedVectorAllLanes()) return false;
1183 return VectorList.Count == 3;
1184 }
1185
1186 bool isVecListThreeQAllLanes() const {
1187 if (!isDoubleSpacedVectorAllLanes()) return false;
1188 return VectorList.Count == 3;
1189 }
1190
Jim Grosbacha57a36a2012-01-25 00:01:08 +00001191 bool isVecListFourDAllLanes() const {
1192 if (!isSingleSpacedVectorAllLanes()) return false;
1193 return VectorList.Count == 4;
1194 }
1195
1196 bool isVecListFourQAllLanes() const {
1197 if (!isDoubleSpacedVectorAllLanes()) return false;
1198 return VectorList.Count == 4;
1199 }
1200
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001201 bool isSingleSpacedVectorIndexed() const {
1202 return Kind == k_VectorListIndexed && !VectorList.isDoubleSpaced;
1203 }
1204 bool isDoubleSpacedVectorIndexed() const {
1205 return Kind == k_VectorListIndexed && VectorList.isDoubleSpaced;
1206 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00001207 bool isVecListOneDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001208 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach7636bf62011-12-02 00:35:16 +00001209 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1210 }
1211
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001212 bool isVecListOneDHWordIndexed() 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 <= 3;
1215 }
1216
1217 bool isVecListOneDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001218 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001219 return VectorList.Count == 1 && VectorList.LaneIndex <= 1;
1220 }
1221
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001222 bool isVecListTwoDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001223 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001224 return VectorList.Count == 2 && VectorList.LaneIndex <= 7;
1225 }
1226
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001227 bool isVecListTwoDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001228 if (!isSingleSpacedVectorIndexed()) return false;
1229 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1230 }
1231
1232 bool isVecListTwoQWordIndexed() const {
1233 if (!isDoubleSpacedVectorIndexed()) return false;
1234 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1235 }
1236
1237 bool isVecListTwoQHWordIndexed() const {
1238 if (!isDoubleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001239 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1240 }
1241
1242 bool isVecListTwoDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001243 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001244 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1245 }
1246
Jim Grosbach3a678af2012-01-23 21:53:26 +00001247 bool isVecListThreeDByteIndexed() const {
1248 if (!isSingleSpacedVectorIndexed()) return false;
1249 return VectorList.Count == 3 && VectorList.LaneIndex <= 7;
1250 }
1251
1252 bool isVecListThreeDHWordIndexed() const {
1253 if (!isSingleSpacedVectorIndexed()) return false;
1254 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1255 }
1256
1257 bool isVecListThreeQWordIndexed() const {
1258 if (!isDoubleSpacedVectorIndexed()) return false;
1259 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1260 }
1261
1262 bool isVecListThreeQHWordIndexed() const {
1263 if (!isDoubleSpacedVectorIndexed()) return false;
1264 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1265 }
1266
1267 bool isVecListThreeDWordIndexed() const {
1268 if (!isSingleSpacedVectorIndexed()) return false;
1269 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1270 }
1271
Jim Grosbache983a132012-01-24 18:37:25 +00001272 bool isVecListFourDByteIndexed() const {
1273 if (!isSingleSpacedVectorIndexed()) return false;
1274 return VectorList.Count == 4 && VectorList.LaneIndex <= 7;
1275 }
1276
1277 bool isVecListFourDHWordIndexed() const {
1278 if (!isSingleSpacedVectorIndexed()) return false;
1279 return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1280 }
1281
1282 bool isVecListFourQWordIndexed() const {
1283 if (!isDoubleSpacedVectorIndexed()) return false;
1284 return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1285 }
1286
1287 bool isVecListFourQHWordIndexed() const {
1288 if (!isDoubleSpacedVectorIndexed()) return false;
1289 return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1290 }
1291
1292 bool isVecListFourDWordIndexed() const {
1293 if (!isSingleSpacedVectorIndexed()) return false;
1294 return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1295 }
1296
Jim Grosbach460a9052011-10-07 23:56:00 +00001297 bool isVectorIndex8() const {
1298 if (Kind != k_VectorIndex) return false;
1299 return VectorIndex.Val < 8;
1300 }
1301 bool isVectorIndex16() const {
1302 if (Kind != k_VectorIndex) return false;
1303 return VectorIndex.Val < 4;
1304 }
1305 bool isVectorIndex32() const {
1306 if (Kind != k_VectorIndex) return false;
1307 return VectorIndex.Val < 2;
1308 }
1309
Jim Grosbach0e387b22011-10-17 22:26:03 +00001310 bool isNEONi8splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001311 if (!isImm()) return false;
Jim Grosbach0e387b22011-10-17 22:26:03 +00001312 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1313 // Must be a constant.
1314 if (!CE) return false;
1315 int64_t Value = CE->getValue();
1316 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1317 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +00001318 return Value >= 0 && Value < 256;
1319 }
Jim Grosbach460a9052011-10-07 23:56:00 +00001320
Jim Grosbachea461102011-10-17 23:09:09 +00001321 bool isNEONi16splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001322 if (!isImm()) return false;
Jim Grosbachea461102011-10-17 23:09:09 +00001323 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1324 // Must be a constant.
1325 if (!CE) return false;
1326 int64_t Value = CE->getValue();
1327 // i16 value in the range [0,255] or [0x0100, 0xff00]
1328 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1329 }
1330
Jim Grosbach6248a542011-10-18 00:22:00 +00001331 bool isNEONi32splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001332 if (!isImm()) return false;
Jim Grosbach6248a542011-10-18 00:22:00 +00001333 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1334 // Must be a constant.
1335 if (!CE) return false;
1336 int64_t Value = CE->getValue();
1337 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1338 return (Value >= 0 && Value < 256) ||
1339 (Value >= 0x0100 && Value <= 0xff00) ||
1340 (Value >= 0x010000 && Value <= 0xff0000) ||
1341 (Value >= 0x01000000 && Value <= 0xff000000);
1342 }
1343
1344 bool isNEONi32vmov() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001345 if (!isImm()) return false;
Jim Grosbach6248a542011-10-18 00:22:00 +00001346 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1347 // Must be a constant.
1348 if (!CE) return false;
1349 int64_t Value = CE->getValue();
1350 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1351 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1352 return (Value >= 0 && Value < 256) ||
1353 (Value >= 0x0100 && Value <= 0xff00) ||
1354 (Value >= 0x010000 && Value <= 0xff0000) ||
1355 (Value >= 0x01000000 && Value <= 0xff000000) ||
1356 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1357 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1358 }
Jim Grosbach9b087852011-12-19 23:51:07 +00001359 bool isNEONi32vmovNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001360 if (!isImm()) return false;
Jim Grosbach9b087852011-12-19 23:51:07 +00001361 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1362 // Must be a constant.
1363 if (!CE) return false;
1364 int64_t Value = ~CE->getValue();
1365 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1366 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1367 return (Value >= 0 && Value < 256) ||
1368 (Value >= 0x0100 && Value <= 0xff00) ||
1369 (Value >= 0x010000 && Value <= 0xff0000) ||
1370 (Value >= 0x01000000 && Value <= 0xff000000) ||
1371 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1372 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1373 }
Jim Grosbach6248a542011-10-18 00:22:00 +00001374
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001375 bool isNEONi64splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001376 if (!isImm()) return false;
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001377 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1378 // Must be a constant.
1379 if (!CE) return false;
1380 uint64_t Value = CE->getValue();
1381 // i64 value with each byte being either 0 or 0xff.
1382 for (unsigned i = 0; i < 8; ++i)
1383 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1384 return true;
1385 }
1386
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001387 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001388 // Add as immediates when possible. Null MCExpr = 0.
1389 if (Expr == 0)
1390 Inst.addOperand(MCOperand::CreateImm(0));
1391 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001392 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1393 else
1394 Inst.addOperand(MCOperand::CreateExpr(Expr));
1395 }
1396
Daniel Dunbar8462b302010-08-11 06:36:53 +00001397 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001398 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001399 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001400 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1401 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001402 }
1403
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001404 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1405 assert(N == 1 && "Invalid number of operands!");
1406 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1407 }
1408
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001409 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1410 assert(N == 1 && "Invalid number of operands!");
1411 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1412 }
1413
1414 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1415 assert(N == 1 && "Invalid number of operands!");
1416 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1417 }
1418
Jim Grosbach89df9962011-08-26 21:43:41 +00001419 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1420 assert(N == 1 && "Invalid number of operands!");
1421 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1422 }
1423
1424 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1425 assert(N == 1 && "Invalid number of operands!");
1426 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1427 }
1428
Jim Grosbachd67641b2010-12-06 18:21:12 +00001429 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1430 assert(N == 1 && "Invalid number of operands!");
1431 Inst.addOperand(MCOperand::CreateReg(getReg()));
1432 }
1433
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001434 void addRegOperands(MCInst &Inst, unsigned N) const {
1435 assert(N == 1 && "Invalid number of operands!");
1436 Inst.addOperand(MCOperand::CreateReg(getReg()));
1437 }
1438
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001439 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001440 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001441 assert(isRegShiftedReg() &&
1442 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001443 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1444 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001445 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001446 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001447 }
1448
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001449 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001450 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001451 assert(isRegShiftedImm() &&
1452 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001453 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Richard Bartonb56e4112012-04-25 18:00:18 +00001454 // Shift of #32 is encoded as 0 where permitted
1455 unsigned Imm = (RegShiftedImm.ShiftImm == 32 ? 0 : RegShiftedImm.ShiftImm);
Owen Anderson92a20222011-07-21 18:54:16 +00001456 Inst.addOperand(MCOperand::CreateImm(
Richard Bartonb56e4112012-04-25 18:00:18 +00001457 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, Imm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001458 }
1459
Jim Grosbach580f4a92011-07-25 22:20:28 +00001460 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001461 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001462 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1463 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001464 }
1465
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001466 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001467 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001468 const SmallVectorImpl<unsigned> &RegList = getRegList();
1469 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001470 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1471 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001472 }
1473
Bill Wendling0f630752010-11-17 04:32:08 +00001474 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1475 addRegListOperands(Inst, N);
1476 }
1477
1478 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1479 addRegListOperands(Inst, N);
1480 }
1481
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001482 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1483 assert(N == 1 && "Invalid number of operands!");
1484 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1485 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1486 }
1487
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001488 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1489 assert(N == 1 && "Invalid number of operands!");
1490 // Munge the lsb/width into a bitfield mask.
1491 unsigned lsb = Bitfield.LSB;
1492 unsigned width = Bitfield.Width;
1493 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1494 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1495 (32 - (lsb + width)));
1496 Inst.addOperand(MCOperand::CreateImm(Mask));
1497 }
1498
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001499 void addImmOperands(MCInst &Inst, unsigned N) const {
1500 assert(N == 1 && "Invalid number of operands!");
1501 addExpr(Inst, getImm());
1502 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001503
Jim Grosbach4050bc42011-12-22 22:19:05 +00001504 void addFBits16Operands(MCInst &Inst, unsigned N) const {
1505 assert(N == 1 && "Invalid number of operands!");
1506 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1507 Inst.addOperand(MCOperand::CreateImm(16 - CE->getValue()));
1508 }
1509
1510 void addFBits32Operands(MCInst &Inst, unsigned N) const {
1511 assert(N == 1 && "Invalid number of operands!");
1512 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1513 Inst.addOperand(MCOperand::CreateImm(32 - CE->getValue()));
1514 }
1515
Jim Grosbach9d390362011-10-03 23:38:36 +00001516 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1517 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach51222d12012-01-20 18:09:51 +00001518 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1519 int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
1520 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach9d390362011-10-03 23:38:36 +00001521 }
1522
Jim Grosbacha77295d2011-09-08 22:07:06 +00001523 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1524 assert(N == 1 && "Invalid number of operands!");
1525 // FIXME: We really want to scale the value here, but the LDRD/STRD
1526 // instruction don't encode operands that way yet.
1527 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1528 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1529 }
1530
Jim Grosbach72f39f82011-08-24 21:22:15 +00001531 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1532 assert(N == 1 && "Invalid number of operands!");
1533 // The immediate is scaled by four in the encoding and is stored
1534 // in the MCInst as such. Lop off the low two bits here.
1535 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1536 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1537 }
1538
Jim Grosbach4e53fe82012-04-05 20:57:13 +00001539 void addImm0_508s4NegOperands(MCInst &Inst, unsigned N) const {
1540 assert(N == 1 && "Invalid number of operands!");
1541 // The immediate is scaled by four in the encoding and is stored
1542 // in the MCInst as such. Lop off the low two bits here.
1543 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1544 Inst.addOperand(MCOperand::CreateImm(-(CE->getValue() / 4)));
1545 }
1546
Jim Grosbach72f39f82011-08-24 21:22:15 +00001547 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1548 assert(N == 1 && "Invalid number of operands!");
1549 // The immediate is scaled by four in the encoding and is stored
1550 // in the MCInst as such. Lop off the low two bits here.
1551 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1552 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1553 }
1554
Jim Grosbachf4943352011-07-25 23:09:14 +00001555 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1556 assert(N == 1 && "Invalid number of operands!");
1557 // The constant encodes as the immediate-1, and we store in the instruction
1558 // the bits as encoded, so subtract off one here.
1559 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1560 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1561 }
1562
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001563 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1564 assert(N == 1 && "Invalid number of operands!");
1565 // The constant encodes as the immediate-1, and we store in the instruction
1566 // the bits as encoded, so subtract off one here.
1567 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1568 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1569 }
1570
Jim Grosbach70939ee2011-08-17 21:51:27 +00001571 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1572 assert(N == 1 && "Invalid number of operands!");
1573 // The constant encodes as the immediate, except for 32, which encodes as
1574 // zero.
1575 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1576 unsigned Imm = CE->getValue();
1577 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1578 }
1579
Jim Grosbachf6c05252011-07-21 17:23:04 +00001580 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1581 assert(N == 1 && "Invalid number of operands!");
1582 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1583 // the instruction as well.
1584 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1585 int Val = CE->getValue();
1586 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1587 }
1588
Jim Grosbach89a63372011-10-28 22:36:30 +00001589 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1590 assert(N == 1 && "Invalid number of operands!");
1591 // The operand is actually a t2_so_imm, but we have its bitwise
1592 // negation in the assembly source, so twiddle it here.
1593 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1594 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1595 }
1596
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001597 void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1598 assert(N == 1 && "Invalid number of operands!");
1599 // The operand is actually a t2_so_imm, but we have its
1600 // negation in the assembly source, so twiddle it here.
1601 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1602 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1603 }
1604
Jim Grosbach4e53fe82012-04-05 20:57:13 +00001605 void addImm0_4095NegOperands(MCInst &Inst, unsigned N) const {
1606 assert(N == 1 && "Invalid number of operands!");
1607 // The operand is actually an imm0_4095, but we have its
1608 // negation in the assembly source, so twiddle it here.
1609 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1610 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1611 }
1612
Jim Grosbache70ec842011-10-28 22:50:54 +00001613 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1614 assert(N == 1 && "Invalid number of operands!");
1615 // The operand is actually a so_imm, but we have its bitwise
1616 // negation in the assembly source, so twiddle it here.
1617 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1618 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1619 }
1620
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001621 void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
1622 assert(N == 1 && "Invalid number of operands!");
1623 // The operand is actually a so_imm, but we have its
1624 // negation in the assembly source, so twiddle it here.
1625 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1626 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1627 }
1628
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001629 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1630 assert(N == 1 && "Invalid number of operands!");
1631 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1632 }
1633
Jim Grosbach7ce05792011-08-03 23:50:40 +00001634 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1635 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001636 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001637 }
1638
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001639 void addMemPCRelImm12Operands(MCInst &Inst, unsigned N) const {
1640 assert(N == 1 && "Invalid number of operands!");
1641 int32_t Imm = Memory.OffsetImm->getValue();
1642 // FIXME: Handle #-0
1643 if (Imm == INT32_MIN) Imm = 0;
1644 Inst.addOperand(MCOperand::CreateImm(Imm));
1645 }
1646
Jim Grosbach57dcb852011-10-11 17:29:55 +00001647 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1648 assert(N == 2 && "Invalid number of operands!");
1649 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1650 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1651 }
1652
Jim Grosbach7ce05792011-08-03 23:50:40 +00001653 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1654 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001655 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1656 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001657 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1658 // Special case for #-0
1659 if (Val == INT32_MIN) Val = 0;
1660 if (Val < 0) Val = -Val;
1661 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1662 } else {
1663 // For register offset, we encode the shift type and negation flag
1664 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001665 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1666 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001667 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001668 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1669 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001670 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001671 }
1672
Jim Grosbach039c2e12011-08-04 23:01:30 +00001673 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1674 assert(N == 2 && "Invalid number of operands!");
1675 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1676 assert(CE && "non-constant AM2OffsetImm operand!");
1677 int32_t Val = CE->getValue();
1678 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1679 // Special case for #-0
1680 if (Val == INT32_MIN) Val = 0;
1681 if (Val < 0) Val = -Val;
1682 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1683 Inst.addOperand(MCOperand::CreateReg(0));
1684 Inst.addOperand(MCOperand::CreateImm(Val));
1685 }
1686
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001687 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1688 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001689 // If we have an immediate that's not a constant, treat it as a label
1690 // reference needing a fixup. If it is a constant, it's something else
1691 // and we reject it.
1692 if (isImm()) {
1693 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1694 Inst.addOperand(MCOperand::CreateReg(0));
1695 Inst.addOperand(MCOperand::CreateImm(0));
1696 return;
1697 }
1698
Jim Grosbache53c87b2011-10-11 15:59:20 +00001699 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1700 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001701 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1702 // Special case for #-0
1703 if (Val == INT32_MIN) Val = 0;
1704 if (Val < 0) Val = -Val;
1705 Val = ARM_AM::getAM3Opc(AddSub, Val);
1706 } else {
1707 // For register offset, we encode the shift type and negation flag
1708 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001709 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001710 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001711 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1712 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001713 Inst.addOperand(MCOperand::CreateImm(Val));
1714 }
1715
1716 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1717 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001718 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001719 int32_t Val =
1720 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1721 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1722 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001723 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001724 }
1725
1726 // Constant offset.
1727 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1728 int32_t Val = CE->getValue();
1729 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1730 // Special case for #-0
1731 if (Val == INT32_MIN) Val = 0;
1732 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001733 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001734 Inst.addOperand(MCOperand::CreateReg(0));
1735 Inst.addOperand(MCOperand::CreateImm(Val));
1736 }
1737
Jim Grosbach7ce05792011-08-03 23:50:40 +00001738 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1739 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach681460f2011-11-01 01:24:45 +00001740 // If we have an immediate that's not a constant, treat it as a label
1741 // reference needing a fixup. If it is a constant, it's something else
1742 // and we reject it.
1743 if (isImm()) {
1744 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1745 Inst.addOperand(MCOperand::CreateImm(0));
1746 return;
1747 }
1748
Jim Grosbach7ce05792011-08-03 23:50:40 +00001749 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001750 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001751 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1752 // Special case for #-0
1753 if (Val == INT32_MIN) Val = 0;
1754 if (Val < 0) Val = -Val;
1755 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001756 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001757 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001758 }
1759
Jim Grosbacha77295d2011-09-08 22:07:06 +00001760 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1761 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001762 // If we have an immediate that's not a constant, treat it as a label
1763 // reference needing a fixup. If it is a constant, it's something else
1764 // and we reject it.
1765 if (isImm()) {
1766 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1767 Inst.addOperand(MCOperand::CreateImm(0));
1768 return;
1769 }
1770
Jim Grosbache53c87b2011-10-11 15:59:20 +00001771 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1772 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001773 Inst.addOperand(MCOperand::CreateImm(Val));
1774 }
1775
Jim Grosbachb6aed502011-09-09 18:37:27 +00001776 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1777 assert(N == 2 && "Invalid number of operands!");
1778 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001779 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1780 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001781 Inst.addOperand(MCOperand::CreateImm(Val));
1782 }
1783
Jim Grosbach7ce05792011-08-03 23:50:40 +00001784 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1785 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001786 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1787 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001788 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001789 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001790
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001791 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1792 addMemImm8OffsetOperands(Inst, N);
1793 }
1794
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001795 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001796 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001797 }
1798
1799 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1800 assert(N == 2 && "Invalid number of operands!");
1801 // If this is an immediate, it's a label reference.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001802 if (isImm()) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001803 addExpr(Inst, getImm());
1804 Inst.addOperand(MCOperand::CreateImm(0));
1805 return;
1806 }
1807
1808 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001809 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1810 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001811 Inst.addOperand(MCOperand::CreateImm(Val));
1812 }
1813
Jim Grosbach7ce05792011-08-03 23:50:40 +00001814 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1815 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001816 // If this is an immediate, it's a label reference.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001817 if (isImm()) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001818 addExpr(Inst, getImm());
1819 Inst.addOperand(MCOperand::CreateImm(0));
1820 return;
1821 }
1822
1823 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001824 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1825 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001826 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001827 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001828
Jim Grosbach7f739be2011-09-19 22:21:13 +00001829 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1830 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001831 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1832 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001833 }
1834
1835 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1836 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001837 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1838 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001839 }
1840
Jim Grosbach7ce05792011-08-03 23:50:40 +00001841 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1842 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001843 unsigned Val =
1844 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1845 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001846 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1847 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001848 Inst.addOperand(MCOperand::CreateImm(Val));
1849 }
1850
Jim Grosbachab899c12011-09-07 23:10:15 +00001851 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1852 assert(N == 3 && "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));
1855 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001856 }
1857
Jim Grosbach7ce05792011-08-03 23:50:40 +00001858 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1859 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001860 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1861 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001862 }
1863
Jim Grosbach60f91a32011-08-19 17:55:24 +00001864 void addMemThumbRIs4Operands(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() / 4) : 0;
1867 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001868 Inst.addOperand(MCOperand::CreateImm(Val));
1869 }
1870
Jim Grosbach38466302011-08-19 18:55:51 +00001871 void addMemThumbRIs2Operands(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() / 2) : 0;
1874 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001875 Inst.addOperand(MCOperand::CreateImm(Val));
1876 }
1877
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001878 void addMemThumbRIs1Operands(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()) : 0;
1881 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001882 Inst.addOperand(MCOperand::CreateImm(Val));
1883 }
1884
Jim Grosbachecd85892011-08-19 18:13:48 +00001885 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1886 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001887 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1888 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001889 Inst.addOperand(MCOperand::CreateImm(Val));
1890 }
1891
Jim Grosbach7ce05792011-08-03 23:50:40 +00001892 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1893 assert(N == 1 && "Invalid number of operands!");
1894 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1895 assert(CE && "non-constant post-idx-imm8 operand!");
1896 int Imm = CE->getValue();
1897 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001898 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001899 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1900 Inst.addOperand(MCOperand::CreateImm(Imm));
1901 }
1902
Jim Grosbach2bd01182011-10-11 21:55:36 +00001903 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1904 assert(N == 1 && "Invalid number of operands!");
1905 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1906 assert(CE && "non-constant post-idx-imm8s4 operand!");
1907 int Imm = CE->getValue();
1908 bool isAdd = Imm >= 0;
1909 if (Imm == INT32_MIN) Imm = 0;
1910 // Immediate is scaled by 4.
1911 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1912 Inst.addOperand(MCOperand::CreateImm(Imm));
1913 }
1914
Jim Grosbach7ce05792011-08-03 23:50:40 +00001915 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1916 assert(N == 2 && "Invalid number of operands!");
1917 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001918 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1919 }
1920
1921 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1922 assert(N == 2 && "Invalid number of operands!");
1923 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1924 // The sign, shift type, and shift amount are encoded in a single operand
1925 // using the AM2 encoding helpers.
1926 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1927 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1928 PostIdxReg.ShiftTy);
1929 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001930 }
1931
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001932 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1933 assert(N == 1 && "Invalid number of operands!");
1934 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1935 }
1936
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001937 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1938 assert(N == 1 && "Invalid number of operands!");
1939 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1940 }
1941
Jim Grosbach6029b6d2011-11-29 23:51:09 +00001942 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach862019c2011-10-18 23:02:30 +00001943 assert(N == 1 && "Invalid number of operands!");
1944 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1945 }
1946
Jim Grosbach7636bf62011-12-02 00:35:16 +00001947 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1948 assert(N == 2 && "Invalid number of operands!");
1949 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1950 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1951 }
1952
Jim Grosbach460a9052011-10-07 23:56:00 +00001953 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1954 assert(N == 1 && "Invalid number of operands!");
1955 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1956 }
1957
1958 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1959 assert(N == 1 && "Invalid number of operands!");
1960 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1961 }
1962
1963 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1964 assert(N == 1 && "Invalid number of operands!");
1965 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1966 }
1967
Jim Grosbach0e387b22011-10-17 22:26:03 +00001968 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1969 assert(N == 1 && "Invalid number of operands!");
1970 // The immediate encodes the type of constant as well as the value.
1971 // Mask in that this is an i8 splat.
1972 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1973 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1974 }
1975
Jim Grosbachea461102011-10-17 23:09:09 +00001976 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1977 assert(N == 1 && "Invalid number of operands!");
1978 // The immediate encodes the type of constant as well as the value.
1979 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1980 unsigned Value = CE->getValue();
1981 if (Value >= 256)
1982 Value = (Value >> 8) | 0xa00;
1983 else
1984 Value |= 0x800;
1985 Inst.addOperand(MCOperand::CreateImm(Value));
1986 }
1987
Jim Grosbach6248a542011-10-18 00:22:00 +00001988 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1989 assert(N == 1 && "Invalid number of operands!");
1990 // The immediate encodes the type of constant as well as the value.
1991 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1992 unsigned Value = CE->getValue();
1993 if (Value >= 256 && Value <= 0xff00)
1994 Value = (Value >> 8) | 0x200;
1995 else if (Value > 0xffff && Value <= 0xff0000)
1996 Value = (Value >> 16) | 0x400;
1997 else if (Value > 0xffffff)
1998 Value = (Value >> 24) | 0x600;
1999 Inst.addOperand(MCOperand::CreateImm(Value));
2000 }
2001
2002 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
2003 assert(N == 1 && "Invalid number of operands!");
2004 // The immediate encodes the type of constant as well as the value.
2005 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2006 unsigned Value = CE->getValue();
2007 if (Value >= 256 && Value <= 0xffff)
2008 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
2009 else if (Value > 0xffff && Value <= 0xffffff)
2010 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
2011 else if (Value > 0xffffff)
2012 Value = (Value >> 24) | 0x600;
2013 Inst.addOperand(MCOperand::CreateImm(Value));
2014 }
2015
Jim Grosbach9b087852011-12-19 23:51:07 +00002016 void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const {
2017 assert(N == 1 && "Invalid number of operands!");
2018 // The immediate encodes the type of constant as well as the value.
2019 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2020 unsigned Value = ~CE->getValue();
2021 if (Value >= 256 && Value <= 0xffff)
2022 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
2023 else if (Value > 0xffff && Value <= 0xffffff)
2024 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
2025 else if (Value > 0xffffff)
2026 Value = (Value >> 24) | 0x600;
2027 Inst.addOperand(MCOperand::CreateImm(Value));
2028 }
2029
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00002030 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
2031 assert(N == 1 && "Invalid number of operands!");
2032 // The immediate encodes the type of constant as well as the value.
2033 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2034 uint64_t Value = CE->getValue();
2035 unsigned Imm = 0;
2036 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
2037 Imm |= (Value & 1) << i;
2038 }
2039 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
2040 }
2041
Jim Grosbachb7f689b2011-07-13 15:34:57 +00002042 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00002043
Jim Grosbach89df9962011-08-26 21:43:41 +00002044 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002045 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00002046 Op->ITMask.Mask = Mask;
2047 Op->StartLoc = S;
2048 Op->EndLoc = S;
2049 return Op;
2050 }
2051
Chris Lattner3a697562010-10-28 17:20:03 +00002052 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002053 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00002054 Op->CC.Val = CC;
2055 Op->StartLoc = S;
2056 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00002057 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00002058 }
2059
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002060 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002061 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002062 Op->Cop.Val = CopVal;
2063 Op->StartLoc = S;
2064 Op->EndLoc = S;
2065 return Op;
2066 }
2067
2068 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002069 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002070 Op->Cop.Val = CopVal;
2071 Op->StartLoc = S;
2072 Op->EndLoc = S;
2073 return Op;
2074 }
2075
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002076 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
2077 ARMOperand *Op = new ARMOperand(k_CoprocOption);
2078 Op->Cop.Val = Val;
2079 Op->StartLoc = S;
2080 Op->EndLoc = E;
2081 return Op;
2082 }
2083
Jim Grosbachd67641b2010-12-06 18:21:12 +00002084 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002085 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00002086 Op->Reg.RegNum = RegNum;
2087 Op->StartLoc = S;
2088 Op->EndLoc = S;
2089 return Op;
2090 }
2091
Chris Lattner3a697562010-10-28 17:20:03 +00002092 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002093 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00002094 Op->Tok.Data = Str.data();
2095 Op->Tok.Length = Str.size();
2096 Op->StartLoc = S;
2097 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00002098 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002099 }
2100
Bill Wendling50d0f582010-11-18 23:43:05 +00002101 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002102 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00002103 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00002104 Op->StartLoc = S;
2105 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002106 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002107 }
2108
Jim Grosbache8606dc2011-07-13 17:50:29 +00002109 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
2110 unsigned SrcReg,
2111 unsigned ShiftReg,
2112 unsigned ShiftImm,
2113 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002114 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002115 Op->RegShiftedReg.ShiftTy = ShTy;
2116 Op->RegShiftedReg.SrcReg = SrcReg;
2117 Op->RegShiftedReg.ShiftReg = ShiftReg;
2118 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002119 Op->StartLoc = S;
2120 Op->EndLoc = E;
2121 return Op;
2122 }
2123
Owen Anderson92a20222011-07-21 18:54:16 +00002124 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
2125 unsigned SrcReg,
2126 unsigned ShiftImm,
2127 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002128 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002129 Op->RegShiftedImm.ShiftTy = ShTy;
2130 Op->RegShiftedImm.SrcReg = SrcReg;
2131 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00002132 Op->StartLoc = S;
2133 Op->EndLoc = E;
2134 return Op;
2135 }
2136
Jim Grosbach580f4a92011-07-25 22:20:28 +00002137 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002138 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002139 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00002140 Op->ShifterImm.isASR = isASR;
2141 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00002142 Op->StartLoc = S;
2143 Op->EndLoc = E;
2144 return Op;
2145 }
2146
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002147 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002148 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002149 Op->RotImm.Imm = Imm;
2150 Op->StartLoc = S;
2151 Op->EndLoc = E;
2152 return Op;
2153 }
2154
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002155 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
2156 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002157 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002158 Op->Bitfield.LSB = LSB;
2159 Op->Bitfield.Width = Width;
2160 Op->StartLoc = S;
2161 Op->EndLoc = E;
2162 return Op;
2163 }
2164
Bill Wendling7729e062010-11-09 22:44:22 +00002165 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00002166 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002167 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002168 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002169
Jim Grosbachd300b942011-09-13 22:56:44 +00002170 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002171 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00002172 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00002173 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002174 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002175
2176 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00002177 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002178 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00002179 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00002180 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002181 Op->StartLoc = StartLoc;
2182 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00002183 return Op;
2184 }
2185
Jim Grosbach862019c2011-10-18 23:02:30 +00002186 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002187 bool isDoubleSpaced, SMLoc S, SMLoc E) {
Jim Grosbach862019c2011-10-18 23:02:30 +00002188 ARMOperand *Op = new ARMOperand(k_VectorList);
2189 Op->VectorList.RegNum = RegNum;
2190 Op->VectorList.Count = Count;
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002191 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach862019c2011-10-18 23:02:30 +00002192 Op->StartLoc = S;
2193 Op->EndLoc = E;
2194 return Op;
2195 }
2196
Jim Grosbach98b05a52011-11-30 01:09:44 +00002197 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002198 bool isDoubleSpaced,
Jim Grosbach98b05a52011-11-30 01:09:44 +00002199 SMLoc S, SMLoc E) {
2200 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
2201 Op->VectorList.RegNum = RegNum;
2202 Op->VectorList.Count = Count;
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002203 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002204 Op->StartLoc = S;
2205 Op->EndLoc = E;
2206 return Op;
2207 }
2208
Jim Grosbach7636bf62011-12-02 00:35:16 +00002209 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002210 unsigned Index,
2211 bool isDoubleSpaced,
2212 SMLoc S, SMLoc E) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002213 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
2214 Op->VectorList.RegNum = RegNum;
2215 Op->VectorList.Count = Count;
2216 Op->VectorList.LaneIndex = Index;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002217 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002218 Op->StartLoc = S;
2219 Op->EndLoc = E;
2220 return Op;
2221 }
2222
Jim Grosbach460a9052011-10-07 23:56:00 +00002223 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
2224 MCContext &Ctx) {
2225 ARMOperand *Op = new ARMOperand(k_VectorIndex);
2226 Op->VectorIndex.Val = Idx;
2227 Op->StartLoc = S;
2228 Op->EndLoc = E;
2229 return Op;
2230 }
2231
Chris Lattner3a697562010-10-28 17:20:03 +00002232 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002233 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00002234 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00002235 Op->StartLoc = S;
2236 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002237 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00002238 }
2239
Jim Grosbach7ce05792011-08-03 23:50:40 +00002240 static ARMOperand *CreateMem(unsigned BaseRegNum,
2241 const MCConstantExpr *OffsetImm,
2242 unsigned OffsetRegNum,
2243 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002244 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00002245 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002246 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00002247 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002248 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00002249 Op->Memory.BaseRegNum = BaseRegNum;
2250 Op->Memory.OffsetImm = OffsetImm;
2251 Op->Memory.OffsetRegNum = OffsetRegNum;
2252 Op->Memory.ShiftType = ShiftType;
2253 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00002254 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00002255 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002256 Op->StartLoc = S;
2257 Op->EndLoc = E;
2258 return Op;
2259 }
Jim Grosbach16c74252010-10-29 14:46:02 +00002260
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002261 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
2262 ARM_AM::ShiftOpc ShiftTy,
2263 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002264 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002265 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002266 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002267 Op->PostIdxReg.isAdd = isAdd;
2268 Op->PostIdxReg.ShiftTy = ShiftTy;
2269 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00002270 Op->StartLoc = S;
2271 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002272 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002273 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002274
2275 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002276 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002277 Op->MBOpt.Val = Opt;
2278 Op->StartLoc = S;
2279 Op->EndLoc = S;
2280 return Op;
2281 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002282
2283 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002284 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002285 Op->IFlags.Val = IFlags;
2286 Op->StartLoc = S;
2287 Op->EndLoc = S;
2288 return Op;
2289 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002290
2291 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002292 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002293 Op->MMask.Val = MMask;
2294 Op->StartLoc = S;
2295 Op->EndLoc = S;
2296 return Op;
2297 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002298};
2299
2300} // end anonymous namespace.
2301
Jim Grosbachb7f689b2011-07-13 15:34:57 +00002302void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002303 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002304 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00002305 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002306 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002307 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00002308 OS << "<ccout " << getReg() << ">";
2309 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002310 case k_ITCondMask: {
Craig Topper032f4412012-05-24 04:11:15 +00002311 static const char *const MaskStr[] = {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002312 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2313 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2314 };
Jim Grosbach89df9962011-08-26 21:43:41 +00002315 assert((ITMask.Mask & 0xf) == ITMask.Mask);
2316 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2317 break;
2318 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002319 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002320 OS << "<coprocessor number: " << getCoproc() << ">";
2321 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002322 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002323 OS << "<coprocessor register: " << getCoproc() << ">";
2324 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002325 case k_CoprocOption:
2326 OS << "<coprocessor option: " << CoprocOption.Val << ">";
2327 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002328 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002329 OS << "<mask: " << getMSRMask() << ">";
2330 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002331 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002332 getImm()->print(OS);
2333 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002334 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002335 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2336 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002337 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002338 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00002339 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002340 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002341 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002342 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002343 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2344 << PostIdxReg.RegNum;
2345 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2346 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2347 << PostIdxReg.ShiftImm;
2348 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00002349 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002350 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002351 OS << "<ARM_PROC::";
2352 unsigned IFlags = getProcIFlags();
2353 for (int i=2; i >= 0; --i)
2354 if (IFlags & (1 << i))
2355 OS << ARM_PROC::IFlagsToString(1 << i);
2356 OS << ">";
2357 break;
2358 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002359 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00002360 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002361 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002362 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00002363 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2364 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00002365 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002366 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00002367 OS << "<so_reg_reg "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002368 << RegShiftedReg.SrcReg << " "
2369 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2370 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson00828302011-03-18 22:50:18 +00002371 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002372 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00002373 OS << "<so_reg_imm "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002374 << RegShiftedImm.SrcReg << " "
2375 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2376 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Anderson92a20222011-07-21 18:54:16 +00002377 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002378 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002379 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2380 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002381 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002382 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2383 << ", width: " << Bitfield.Width << ">";
2384 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002385 case k_RegisterList:
2386 case k_DPRRegisterList:
2387 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00002388 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002389
Bill Wendling5fa22a12010-11-09 23:28:44 +00002390 const SmallVectorImpl<unsigned> &RegList = getRegList();
2391 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002392 I = RegList.begin(), E = RegList.end(); I != E; ) {
2393 OS << *I;
2394 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002395 }
2396
2397 OS << ">";
2398 break;
2399 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002400 case k_VectorList:
2401 OS << "<vector_list " << VectorList.Count << " * "
2402 << VectorList.RegNum << ">";
2403 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002404 case k_VectorListAllLanes:
2405 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2406 << VectorList.RegNum << ">";
2407 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002408 case k_VectorListIndexed:
2409 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2410 << VectorList.Count << " * " << VectorList.RegNum << ">";
2411 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002412 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002413 OS << "'" << getToken() << "'";
2414 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00002415 case k_VectorIndex:
2416 OS << "<vectorindex " << getVectorIndex() << ">";
2417 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002418 }
2419}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00002420
2421/// @name Auto-generated Match Functions
2422/// {
2423
2424static unsigned MatchRegisterName(StringRef Name);
2425
2426/// }
2427
Bob Wilson69df7232011-02-03 21:46:10 +00002428bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2429 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbacha39cda72011-12-14 02:16:11 +00002430 StartLoc = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002431 RegNo = tryParseRegister();
Jim Grosbacha39cda72011-12-14 02:16:11 +00002432 EndLoc = Parser.getTok().getLoc();
Roman Divackybf755322011-01-27 17:14:22 +00002433
2434 return (RegNo == (unsigned)-1);
2435}
2436
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002437/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002438/// and if it is a register name the token is eaten and the register number is
2439/// returned. Otherwise return -1.
2440///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002441int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002442 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002443 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002444
Benjamin Kramer59085362011-11-06 20:37:06 +00002445 std::string lowerCase = Tok.getString().lower();
Owen Anderson0c9f2502011-01-13 22:50:36 +00002446 unsigned RegNum = MatchRegisterName(lowerCase);
2447 if (!RegNum) {
2448 RegNum = StringSwitch<unsigned>(lowerCase)
2449 .Case("r13", ARM::SP)
2450 .Case("r14", ARM::LR)
2451 .Case("r15", ARM::PC)
2452 .Case("ip", ARM::R12)
Jim Grosbach40e28552011-12-08 19:27:38 +00002453 // Additional register name aliases for 'gas' compatibility.
2454 .Case("a1", ARM::R0)
2455 .Case("a2", ARM::R1)
2456 .Case("a3", ARM::R2)
2457 .Case("a4", ARM::R3)
2458 .Case("v1", ARM::R4)
2459 .Case("v2", ARM::R5)
2460 .Case("v3", ARM::R6)
2461 .Case("v4", ARM::R7)
2462 .Case("v5", ARM::R8)
2463 .Case("v6", ARM::R9)
2464 .Case("v7", ARM::R10)
2465 .Case("v8", ARM::R11)
2466 .Case("sb", ARM::R9)
2467 .Case("sl", ARM::R10)
2468 .Case("fp", ARM::R11)
Owen Anderson0c9f2502011-01-13 22:50:36 +00002469 .Default(0);
2470 }
Jim Grosbacha39cda72011-12-14 02:16:11 +00002471 if (!RegNum) {
Jim Grosbachaee718b2011-12-20 23:11:00 +00002472 // Check for aliases registered via .req. Canonicalize to lower case.
2473 // That's more consistent since register names are case insensitive, and
2474 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2475 StringMap<unsigned>::const_iterator Entry = RegisterReqs.find(lowerCase);
Jim Grosbacha39cda72011-12-14 02:16:11 +00002476 // If no match, return failure.
2477 if (Entry == RegisterReqs.end())
2478 return -1;
2479 Parser.Lex(); // Eat identifier token.
2480 return Entry->getValue();
2481 }
Bob Wilson69df7232011-02-03 21:46:10 +00002482
Chris Lattnere5658fa2010-10-30 04:09:10 +00002483 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002484
Chris Lattnere5658fa2010-10-30 04:09:10 +00002485 return RegNum;
2486}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002487
Jim Grosbach19906722011-07-13 18:49:30 +00002488// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2489// If a recoverable error occurs, return 1. If an irrecoverable error
2490// occurs, return -1. An irrecoverable error is one where tokens have been
2491// consumed in the process of trying to parse the shifter (i.e., when it is
2492// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002493int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002494 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2495 SMLoc S = Parser.getTok().getLoc();
2496 const AsmToken &Tok = Parser.getTok();
2497 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2498
Benjamin Kramer59085362011-11-06 20:37:06 +00002499 std::string lowerCase = Tok.getString().lower();
Owen Anderson00828302011-03-18 22:50:18 +00002500 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbachaf4edea2011-12-07 23:40:58 +00002501 .Case("asl", ARM_AM::lsl)
Owen Anderson00828302011-03-18 22:50:18 +00002502 .Case("lsl", ARM_AM::lsl)
2503 .Case("lsr", ARM_AM::lsr)
2504 .Case("asr", ARM_AM::asr)
2505 .Case("ror", ARM_AM::ror)
2506 .Case("rrx", ARM_AM::rrx)
2507 .Default(ARM_AM::no_shift);
2508
2509 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002510 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002511
Jim Grosbache8606dc2011-07-13 17:50:29 +00002512 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002513
Jim Grosbache8606dc2011-07-13 17:50:29 +00002514 // The source register for the shift has already been added to the
2515 // operand list, so we need to pop it off and combine it into the shifted
2516 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002517 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002518 if (!PrevOp->isReg())
2519 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2520 int SrcReg = PrevOp->getReg();
2521 int64_t Imm = 0;
2522 int ShiftReg = 0;
2523 if (ShiftTy == ARM_AM::rrx) {
2524 // RRX Doesn't have an explicit shift amount. The encoder expects
2525 // the shift register to be the same as the source register. Seems odd,
2526 // but OK.
2527 ShiftReg = SrcReg;
2528 } else {
2529 // Figure out if this is shifted by a constant or a register (for non-RRX).
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00002530 if (Parser.getTok().is(AsmToken::Hash) ||
2531 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbache8606dc2011-07-13 17:50:29 +00002532 Parser.Lex(); // Eat hash.
2533 SMLoc ImmLoc = Parser.getTok().getLoc();
2534 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002535 if (getParser().ParseExpression(ShiftExpr)) {
2536 Error(ImmLoc, "invalid immediate shift value");
2537 return -1;
2538 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002539 // The expression must be evaluatable as an immediate.
2540 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002541 if (!CE) {
2542 Error(ImmLoc, "invalid immediate shift value");
2543 return -1;
2544 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002545 // Range check the immediate.
2546 // lsl, ror: 0 <= imm <= 31
2547 // lsr, asr: 0 <= imm <= 32
2548 Imm = CE->getValue();
2549 if (Imm < 0 ||
2550 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2551 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002552 Error(ImmLoc, "immediate shift value out of range");
2553 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002554 }
Jim Grosbachde626ad2011-12-22 17:37:00 +00002555 // shift by zero is a nop. Always send it through as lsl.
2556 // ('as' compatibility)
2557 if (Imm == 0)
2558 ShiftTy = ARM_AM::lsl;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002559 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002560 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002561 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002562 if (ShiftReg == -1) {
2563 Error (L, "expected immediate or register in shift operand");
2564 return -1;
2565 }
2566 } else {
2567 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002568 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002569 return -1;
2570 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002571 }
2572
Owen Anderson92a20222011-07-21 18:54:16 +00002573 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2574 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002575 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002576 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002577 else
2578 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2579 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002580
Jim Grosbach19906722011-07-13 18:49:30 +00002581 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002582}
2583
2584
Bill Wendling50d0f582010-11-18 23:43:05 +00002585/// Try to parse a register name. The token must be an Identifier when called.
2586/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2587/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002588///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002589/// TODO this is likely to change to allow different register types and or to
2590/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002591bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002592tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002593 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002594 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002595 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002596 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002597
Bill Wendling50d0f582010-11-18 23:43:05 +00002598 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002599
Chris Lattnere5658fa2010-10-30 04:09:10 +00002600 const AsmToken &ExclaimTok = Parser.getTok();
2601 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002602 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2603 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002604 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002605 return false;
2606 }
2607
2608 // Also check for an index operand. This is only legal for vector registers,
2609 // but that'll get caught OK in operand matching, so we don't need to
2610 // explicitly filter everything else out here.
2611 if (Parser.getTok().is(AsmToken::LBrac)) {
2612 SMLoc SIdx = Parser.getTok().getLoc();
2613 Parser.Lex(); // Eat left bracket token.
2614
2615 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002616 if (getParser().ParseExpression(ImmVal))
Jim Grosbach24dda212012-01-31 23:51:09 +00002617 return true;
Jim Grosbach460a9052011-10-07 23:56:00 +00002618 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbachef4d3eb2012-01-26 15:56:45 +00002619 if (!MCE)
2620 return TokError("immediate value expected for vector index");
Jim Grosbach460a9052011-10-07 23:56:00 +00002621
2622 SMLoc E = Parser.getTok().getLoc();
Jim Grosbachef4d3eb2012-01-26 15:56:45 +00002623 if (Parser.getTok().isNot(AsmToken::RBrac))
2624 return Error(E, "']' expected");
Jim Grosbach460a9052011-10-07 23:56:00 +00002625
2626 Parser.Lex(); // Eat right bracket token.
2627
2628 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2629 SIdx, E,
2630 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002631 }
2632
Bill Wendling50d0f582010-11-18 23:43:05 +00002633 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002634}
2635
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002636/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2637/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2638/// "c5", ...
2639static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002640 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2641 // but efficient.
2642 switch (Name.size()) {
David Blaikie4d6ccb52012-01-20 21:51:11 +00002643 default: return -1;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002644 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002645 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002646 return -1;
2647 switch (Name[1]) {
2648 default: return -1;
2649 case '0': return 0;
2650 case '1': return 1;
2651 case '2': return 2;
2652 case '3': return 3;
2653 case '4': return 4;
2654 case '5': return 5;
2655 case '6': return 6;
2656 case '7': return 7;
2657 case '8': return 8;
2658 case '9': return 9;
2659 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002660 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002661 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002662 return -1;
2663 switch (Name[2]) {
2664 default: return -1;
2665 case '0': return 10;
2666 case '1': return 11;
2667 case '2': return 12;
2668 case '3': return 13;
2669 case '4': return 14;
2670 case '5': return 15;
2671 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002672 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002673}
2674
Jim Grosbach89df9962011-08-26 21:43:41 +00002675/// parseITCondCode - Try to parse a condition code for an IT instruction.
2676ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2677parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2678 SMLoc S = Parser.getTok().getLoc();
2679 const AsmToken &Tok = Parser.getTok();
2680 if (!Tok.is(AsmToken::Identifier))
2681 return MatchOperand_NoMatch;
Richard Barton04a09a42012-04-27 17:34:01 +00002682 unsigned CC = StringSwitch<unsigned>(Tok.getString().lower())
Jim Grosbach89df9962011-08-26 21:43:41 +00002683 .Case("eq", ARMCC::EQ)
2684 .Case("ne", ARMCC::NE)
2685 .Case("hs", ARMCC::HS)
2686 .Case("cs", ARMCC::HS)
2687 .Case("lo", ARMCC::LO)
2688 .Case("cc", ARMCC::LO)
2689 .Case("mi", ARMCC::MI)
2690 .Case("pl", ARMCC::PL)
2691 .Case("vs", ARMCC::VS)
2692 .Case("vc", ARMCC::VC)
2693 .Case("hi", ARMCC::HI)
2694 .Case("ls", ARMCC::LS)
2695 .Case("ge", ARMCC::GE)
2696 .Case("lt", ARMCC::LT)
2697 .Case("gt", ARMCC::GT)
2698 .Case("le", ARMCC::LE)
2699 .Case("al", ARMCC::AL)
2700 .Default(~0U);
2701 if (CC == ~0U)
2702 return MatchOperand_NoMatch;
2703 Parser.Lex(); // Eat the token.
2704
2705 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2706
2707 return MatchOperand_Success;
2708}
2709
Jim Grosbach43904292011-07-25 20:14:50 +00002710/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002711/// token must be an Identifier when called, and if it is a coprocessor
2712/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002713ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002714parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002715 SMLoc S = Parser.getTok().getLoc();
2716 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002717 if (Tok.isNot(AsmToken::Identifier))
2718 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002719
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002720 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002721 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002722 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002723
2724 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002725 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002726 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002727}
2728
Jim Grosbach43904292011-07-25 20:14:50 +00002729/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002730/// token must be an Identifier when called, and if it is a coprocessor
2731/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002732ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002733parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002734 SMLoc S = Parser.getTok().getLoc();
2735 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002736 if (Tok.isNot(AsmToken::Identifier))
2737 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002738
2739 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2740 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002741 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002742
2743 Parser.Lex(); // Eat identifier token.
2744 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002745 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002746}
2747
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002748/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2749/// coproc_option : '{' imm0_255 '}'
2750ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2751parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2752 SMLoc S = Parser.getTok().getLoc();
2753
2754 // If this isn't a '{', this isn't a coprocessor immediate operand.
2755 if (Parser.getTok().isNot(AsmToken::LCurly))
2756 return MatchOperand_NoMatch;
2757 Parser.Lex(); // Eat the '{'
2758
2759 const MCExpr *Expr;
2760 SMLoc Loc = Parser.getTok().getLoc();
2761 if (getParser().ParseExpression(Expr)) {
2762 Error(Loc, "illegal expression");
2763 return MatchOperand_ParseFail;
2764 }
2765 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2766 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2767 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2768 return MatchOperand_ParseFail;
2769 }
2770 int Val = CE->getValue();
2771
2772 // Check for and consume the closing '}'
2773 if (Parser.getTok().isNot(AsmToken::RCurly))
2774 return MatchOperand_ParseFail;
2775 SMLoc E = Parser.getTok().getLoc();
2776 Parser.Lex(); // Eat the '}'
2777
2778 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2779 return MatchOperand_Success;
2780}
2781
Jim Grosbachd0588e22011-09-14 18:08:35 +00002782// For register list parsing, we need to map from raw GPR register numbering
2783// to the enumeration values. The enumeration values aren't sorted by
2784// register number due to our using "sp", "lr" and "pc" as canonical names.
2785static unsigned getNextRegister(unsigned Reg) {
2786 // If this is a GPR, we need to do it manually, otherwise we can rely
2787 // on the sort ordering of the enumeration since the other reg-classes
2788 // are sane.
2789 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2790 return Reg + 1;
2791 switch(Reg) {
Craig Topperbc219812012-02-07 02:50:20 +00002792 default: llvm_unreachable("Invalid GPR number!");
Jim Grosbachd0588e22011-09-14 18:08:35 +00002793 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2794 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2795 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2796 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2797 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2798 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2799 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2800 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2801 }
2802}
2803
Jim Grosbachce485e72011-11-11 21:27:40 +00002804// Return the low-subreg of a given Q register.
2805static unsigned getDRegFromQReg(unsigned QReg) {
2806 switch (QReg) {
2807 default: llvm_unreachable("expected a Q register!");
2808 case ARM::Q0: return ARM::D0;
2809 case ARM::Q1: return ARM::D2;
2810 case ARM::Q2: return ARM::D4;
2811 case ARM::Q3: return ARM::D6;
2812 case ARM::Q4: return ARM::D8;
2813 case ARM::Q5: return ARM::D10;
2814 case ARM::Q6: return ARM::D12;
2815 case ARM::Q7: return ARM::D14;
2816 case ARM::Q8: return ARM::D16;
Jim Grosbach25e0a872011-11-15 21:01:30 +00002817 case ARM::Q9: return ARM::D18;
Jim Grosbachce485e72011-11-11 21:27:40 +00002818 case ARM::Q10: return ARM::D20;
2819 case ARM::Q11: return ARM::D22;
2820 case ARM::Q12: return ARM::D24;
2821 case ARM::Q13: return ARM::D26;
2822 case ARM::Q14: return ARM::D28;
2823 case ARM::Q15: return ARM::D30;
2824 }
2825}
2826
Jim Grosbachd0588e22011-09-14 18:08:35 +00002827/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002828bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002829parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002830 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002831 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002832 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002833 Parser.Lex(); // Eat '{' token.
2834 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002835
Jim Grosbachd0588e22011-09-14 18:08:35 +00002836 // Check the first register in the list to see what register class
2837 // this is a list of.
2838 int Reg = tryParseRegister();
2839 if (Reg == -1)
2840 return Error(RegLoc, "register expected");
2841
Jim Grosbachce485e72011-11-11 21:27:40 +00002842 // The reglist instructions have at most 16 registers, so reserve
2843 // space for that many.
2844 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2845
2846 // Allow Q regs and just interpret them as the two D sub-registers.
2847 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2848 Reg = getDRegFromQReg(Reg);
2849 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2850 ++Reg;
2851 }
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002852 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002853 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2854 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2855 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2856 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2857 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2858 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2859 else
2860 return Error(RegLoc, "invalid register in register list");
2861
Jim Grosbachce485e72011-11-11 21:27:40 +00002862 // Store the register.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002863 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002864
Jim Grosbachd0588e22011-09-14 18:08:35 +00002865 // This starts immediately after the first register token in the list,
2866 // so we can see either a comma or a minus (range separator) as a legal
2867 // next token.
2868 while (Parser.getTok().is(AsmToken::Comma) ||
2869 Parser.getTok().is(AsmToken::Minus)) {
2870 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache43862b2011-11-15 23:19:15 +00002871 Parser.Lex(); // Eat the minus.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002872 SMLoc EndLoc = Parser.getTok().getLoc();
2873 int EndReg = tryParseRegister();
2874 if (EndReg == -1)
2875 return Error(EndLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002876 // Allow Q regs and just interpret them as the two D sub-registers.
2877 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2878 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002879 // If the register is the same as the start reg, there's nothing
2880 // more to do.
2881 if (Reg == EndReg)
2882 continue;
2883 // The register must be in the same register class as the first.
2884 if (!RC->contains(EndReg))
2885 return Error(EndLoc, "invalid register in register list");
2886 // Ranges must go from low to high.
2887 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2888 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002889
Jim Grosbachd0588e22011-09-14 18:08:35 +00002890 // Add all the registers in the range to the register list.
2891 while (Reg != EndReg) {
2892 Reg = getNextRegister(Reg);
2893 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2894 }
2895 continue;
2896 }
2897 Parser.Lex(); // Eat the comma.
2898 RegLoc = Parser.getTok().getLoc();
2899 int OldReg = Reg;
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002900 const AsmToken RegTok = Parser.getTok();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002901 Reg = tryParseRegister();
2902 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002903 return Error(RegLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002904 // Allow Q regs and just interpret them as the two D sub-registers.
2905 bool isQReg = false;
2906 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2907 Reg = getDRegFromQReg(Reg);
2908 isQReg = true;
2909 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002910 // The register must be in the same register class as the first.
2911 if (!RC->contains(Reg))
2912 return Error(RegLoc, "invalid register in register list");
2913 // List must be monotonically increasing.
Jim Grosbachbe7cf2b2012-03-16 20:48:38 +00002914 if (getARMRegisterNumbering(Reg) < getARMRegisterNumbering(OldReg)) {
2915 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2916 Warning(RegLoc, "register list not in ascending order");
2917 else
2918 return Error(RegLoc, "register list not in ascending order");
2919 }
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002920 if (getARMRegisterNumbering(Reg) == getARMRegisterNumbering(OldReg)) {
2921 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
2922 ") in register list");
2923 continue;
2924 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002925 // VFP register lists must also be contiguous.
2926 // It's OK to use the enumeration values directly here rather, as the
2927 // VFP register classes have the enum sorted properly.
2928 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2929 Reg != OldReg + 1)
2930 return Error(RegLoc, "non-contiguous register range");
2931 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbachce485e72011-11-11 21:27:40 +00002932 if (isQReg)
2933 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002934 }
2935
Jim Grosbachd0588e22011-09-14 18:08:35 +00002936 SMLoc E = Parser.getTok().getLoc();
2937 if (Parser.getTok().isNot(AsmToken::RCurly))
2938 return Error(E, "'}' expected");
2939 Parser.Lex(); // Eat '}' token.
2940
Jim Grosbach27debd62011-12-13 21:48:29 +00002941 // Push the register list operand.
Bill Wendling50d0f582010-11-18 23:43:05 +00002942 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
Jim Grosbach27debd62011-12-13 21:48:29 +00002943
2944 // The ARM system instruction variants for LDM/STM have a '^' token here.
2945 if (Parser.getTok().is(AsmToken::Caret)) {
2946 Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
2947 Parser.Lex(); // Eat '^' token.
2948 }
2949
Bill Wendling50d0f582010-11-18 23:43:05 +00002950 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002951}
2952
Jim Grosbach98b05a52011-11-30 01:09:44 +00002953// Helper function to parse the lane index for vector lists.
2954ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach7636bf62011-12-02 00:35:16 +00002955parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2956 Index = 0; // Always return a defined index value.
Jim Grosbach98b05a52011-11-30 01:09:44 +00002957 if (Parser.getTok().is(AsmToken::LBrac)) {
2958 Parser.Lex(); // Eat the '['.
2959 if (Parser.getTok().is(AsmToken::RBrac)) {
2960 // "Dn[]" is the 'all lanes' syntax.
2961 LaneKind = AllLanes;
2962 Parser.Lex(); // Eat the ']'.
2963 return MatchOperand_Success;
2964 }
Jim Grosbachceee9842012-03-19 20:39:53 +00002965
2966 // There's an optional '#' token here. Normally there wouldn't be, but
2967 // inline assemble puts one in, and it's friendly to accept that.
2968 if (Parser.getTok().is(AsmToken::Hash))
2969 Parser.Lex(); // Eat the '#'
2970
Jim Grosbachc9313252011-12-21 01:19:23 +00002971 const MCExpr *LaneIndex;
2972 SMLoc Loc = Parser.getTok().getLoc();
2973 if (getParser().ParseExpression(LaneIndex)) {
2974 Error(Loc, "illegal expression");
2975 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002976 }
Jim Grosbachc9313252011-12-21 01:19:23 +00002977 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LaneIndex);
2978 if (!CE) {
2979 Error(Loc, "lane index must be empty or an integer");
2980 return MatchOperand_ParseFail;
2981 }
2982 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2983 Error(Parser.getTok().getLoc(), "']' expected");
2984 return MatchOperand_ParseFail;
2985 }
2986 Parser.Lex(); // Eat the ']'.
2987 int64_t Val = CE->getValue();
2988
2989 // FIXME: Make this range check context sensitive for .8, .16, .32.
2990 if (Val < 0 || Val > 7) {
2991 Error(Parser.getTok().getLoc(), "lane index out of range");
2992 return MatchOperand_ParseFail;
2993 }
2994 Index = Val;
2995 LaneKind = IndexedLane;
2996 return MatchOperand_Success;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002997 }
2998 LaneKind = NoLanes;
2999 return MatchOperand_Success;
3000}
3001
Jim Grosbach862019c2011-10-18 23:02:30 +00003002// parse a vector register list
3003ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3004parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003005 VectorLaneTy LaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003006 unsigned LaneIndex;
Jim Grosbach5c984e42011-11-15 21:45:55 +00003007 SMLoc S = Parser.getTok().getLoc();
3008 // As an extension (to match gas), support a plain D register or Q register
3009 // (without encosing curly braces) as a single or double entry list,
3010 // respectively.
3011 if (Parser.getTok().is(AsmToken::Identifier)) {
3012 int Reg = tryParseRegister();
3013 if (Reg == -1)
3014 return MatchOperand_NoMatch;
3015 SMLoc E = Parser.getTok().getLoc();
3016 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00003017 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00003018 if (Res != MatchOperand_Success)
3019 return Res;
3020 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003021 case NoLanes:
3022 E = Parser.getTok().getLoc();
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003023 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003024 break;
3025 case AllLanes:
3026 E = Parser.getTok().getLoc();
Jim Grosbach3471d4f2011-12-21 00:38:54 +00003027 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false,
3028 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003029 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003030 case IndexedLane:
3031 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00003032 LaneIndex,
3033 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00003034 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003035 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00003036 return MatchOperand_Success;
3037 }
3038 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
3039 Reg = getDRegFromQReg(Reg);
Jim Grosbach7636bf62011-12-02 00:35:16 +00003040 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00003041 if (Res != MatchOperand_Success)
3042 return Res;
3043 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003044 case NoLanes:
3045 E = Parser.getTok().getLoc();
Jim Grosbach28f08c92012-03-05 19:33:30 +00003046 Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0,
Jim Grosbachc0fc4502012-03-06 22:01:44 +00003047 &ARMMCRegisterClasses[ARM::DPairRegClassID]);
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003048 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003049 break;
3050 case AllLanes:
3051 E = Parser.getTok().getLoc();
Jim Grosbachc0fc4502012-03-06 22:01:44 +00003052 Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0,
3053 &ARMMCRegisterClasses[ARM::DPairRegClassID]);
Jim Grosbach3471d4f2011-12-21 00:38:54 +00003054 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, false,
3055 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003056 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003057 case IndexedLane:
3058 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00003059 LaneIndex,
3060 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00003061 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003062 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00003063 return MatchOperand_Success;
3064 }
3065 Error(S, "vector register expected");
3066 return MatchOperand_ParseFail;
3067 }
3068
3069 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbach862019c2011-10-18 23:02:30 +00003070 return MatchOperand_NoMatch;
3071
Jim Grosbach862019c2011-10-18 23:02:30 +00003072 Parser.Lex(); // Eat '{' token.
3073 SMLoc RegLoc = Parser.getTok().getLoc();
3074
3075 int Reg = tryParseRegister();
3076 if (Reg == -1) {
3077 Error(RegLoc, "register expected");
3078 return MatchOperand_ParseFail;
3079 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003080 unsigned Count = 1;
Jim Grosbach276ed032011-12-15 21:54:55 +00003081 int Spacing = 0;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003082 unsigned FirstReg = Reg;
3083 // The list is of D registers, but we also allow Q regs and just interpret
3084 // them as the two D sub-registers.
3085 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
3086 FirstReg = Reg = getDRegFromQReg(Reg);
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003087 Spacing = 1; // double-spacing requires explicit D registers, otherwise
3088 // it's ambiguous with four-register single spaced.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003089 ++Reg;
3090 ++Count;
3091 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00003092 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003093 return MatchOperand_ParseFail;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003094
Jim Grosbache43862b2011-11-15 23:19:15 +00003095 while (Parser.getTok().is(AsmToken::Comma) ||
3096 Parser.getTok().is(AsmToken::Minus)) {
3097 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003098 if (!Spacing)
3099 Spacing = 1; // Register range implies a single spaced list.
3100 else if (Spacing == 2) {
3101 Error(Parser.getTok().getLoc(),
3102 "sequential registers in double spaced list");
3103 return MatchOperand_ParseFail;
3104 }
Jim Grosbache43862b2011-11-15 23:19:15 +00003105 Parser.Lex(); // Eat the minus.
3106 SMLoc EndLoc = Parser.getTok().getLoc();
3107 int EndReg = tryParseRegister();
3108 if (EndReg == -1) {
3109 Error(EndLoc, "register expected");
3110 return MatchOperand_ParseFail;
3111 }
3112 // Allow Q regs and just interpret them as the two D sub-registers.
3113 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
3114 EndReg = getDRegFromQReg(EndReg) + 1;
3115 // If the register is the same as the start reg, there's nothing
3116 // more to do.
3117 if (Reg == EndReg)
3118 continue;
3119 // The register must be in the same register class as the first.
3120 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
3121 Error(EndLoc, "invalid register in register list");
3122 return MatchOperand_ParseFail;
3123 }
3124 // Ranges must go from low to high.
3125 if (Reg > EndReg) {
3126 Error(EndLoc, "bad range in register list");
3127 return MatchOperand_ParseFail;
3128 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00003129 // Parse the lane specifier if present.
3130 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003131 unsigned NextLaneIndex;
3132 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003133 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003134 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003135 Error(EndLoc, "mismatched lane index in register list");
3136 return MatchOperand_ParseFail;
3137 }
3138 EndLoc = Parser.getTok().getLoc();
Jim Grosbache43862b2011-11-15 23:19:15 +00003139
3140 // Add all the registers in the range to the register list.
3141 Count += EndReg - Reg;
3142 Reg = EndReg;
3143 continue;
3144 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003145 Parser.Lex(); // Eat the comma.
3146 RegLoc = Parser.getTok().getLoc();
3147 int OldReg = Reg;
3148 Reg = tryParseRegister();
3149 if (Reg == -1) {
3150 Error(RegLoc, "register expected");
3151 return MatchOperand_ParseFail;
3152 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003153 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00003154 // It's OK to use the enumeration values directly here rather, as the
3155 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003156 //
3157 // The list is of D registers, but we also allow Q regs and just interpret
3158 // them as the two D sub-registers.
3159 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003160 if (!Spacing)
3161 Spacing = 1; // Register range implies a single spaced list.
3162 else if (Spacing == 2) {
3163 Error(RegLoc,
3164 "invalid register in double-spaced list (must be 'D' register')");
3165 return MatchOperand_ParseFail;
3166 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003167 Reg = getDRegFromQReg(Reg);
3168 if (Reg != OldReg + 1) {
3169 Error(RegLoc, "non-contiguous register range");
3170 return MatchOperand_ParseFail;
3171 }
3172 ++Reg;
3173 Count += 2;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003174 // Parse the lane specifier if present.
3175 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003176 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003177 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003178 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003179 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003180 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003181 Error(EndLoc, "mismatched lane index in register list");
3182 return MatchOperand_ParseFail;
3183 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003184 continue;
3185 }
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003186 // Normal D register.
3187 // Figure out the register spacing (single or double) of the list if
3188 // we don't know it already.
3189 if (!Spacing)
3190 Spacing = 1 + (Reg == OldReg + 2);
3191
3192 // Just check that it's contiguous and keep going.
3193 if (Reg != OldReg + Spacing) {
Jim Grosbach862019c2011-10-18 23:02:30 +00003194 Error(RegLoc, "non-contiguous register range");
3195 return MatchOperand_ParseFail;
3196 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003197 ++Count;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003198 // Parse the lane specifier if present.
3199 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003200 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003201 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003202 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003203 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003204 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003205 Error(EndLoc, "mismatched lane index in register list");
3206 return MatchOperand_ParseFail;
3207 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003208 }
3209
3210 SMLoc E = Parser.getTok().getLoc();
3211 if (Parser.getTok().isNot(AsmToken::RCurly)) {
3212 Error(E, "'}' expected");
3213 return MatchOperand_ParseFail;
3214 }
3215 Parser.Lex(); // Eat '}' token.
3216
Jim Grosbach98b05a52011-11-30 01:09:44 +00003217 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003218 case NoLanes:
Jim Grosbachc0fc4502012-03-06 22:01:44 +00003219 // Two-register operands have been converted to the
Jim Grosbachc3384c92012-03-05 21:43:40 +00003220 // composite register classes.
3221 if (Count == 2) {
3222 const MCRegisterClass *RC = (Spacing == 1) ?
3223 &ARMMCRegisterClasses[ARM::DPairRegClassID] :
3224 &ARMMCRegisterClasses[ARM::DPairSpcRegClassID];
3225 FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC);
3226 }
Jim Grosbach28f08c92012-03-05 19:33:30 +00003227
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003228 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count,
3229 (Spacing == 2), S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003230 break;
3231 case AllLanes:
Jim Grosbachc0fc4502012-03-06 22:01:44 +00003232 // Two-register operands have been converted to the
3233 // composite register classes.
Jim Grosbach4d0983a2012-03-06 23:10:38 +00003234 if (Count == 2) {
3235 const MCRegisterClass *RC = (Spacing == 1) ?
3236 &ARMMCRegisterClasses[ARM::DPairRegClassID] :
3237 &ARMMCRegisterClasses[ARM::DPairSpcRegClassID];
Jim Grosbachc0fc4502012-03-06 22:01:44 +00003238 FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC);
3239 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00003240 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00003241 (Spacing == 2),
Jim Grosbach98b05a52011-11-30 01:09:44 +00003242 S, E));
3243 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003244 case IndexedLane:
3245 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00003246 LaneIndex,
3247 (Spacing == 2),
3248 S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00003249 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003250 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003251 return MatchOperand_Success;
3252}
3253
Jim Grosbach43904292011-07-25 20:14:50 +00003254/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00003255ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003256parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003257 SMLoc S = Parser.getTok().getLoc();
3258 const AsmToken &Tok = Parser.getTok();
Richard Bartonb6918202012-06-27 09:36:19 +00003259 if (!Tok.is(AsmToken::Identifier))
3260 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003261 StringRef OptStr = Tok.getString();
3262
Richard Barton4acefe12012-06-27 09:48:23 +00003263 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()).lower())
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003264 .Case("sy", ARM_MB::SY)
3265 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003266 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003267 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003268 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003269 .Case("ishst", ARM_MB::ISHST)
3270 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003271 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003272 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003273 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003274 .Case("osh", ARM_MB::OSH)
3275 .Case("oshst", ARM_MB::OSHST)
3276 .Default(~0U);
3277
3278 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00003279 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003280
3281 Parser.Lex(); // Eat identifier token.
3282 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00003283 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003284}
3285
Jim Grosbach43904292011-07-25 20:14:50 +00003286/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003287ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003288parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003289 SMLoc S = Parser.getTok().getLoc();
3290 const AsmToken &Tok = Parser.getTok();
Richard Bartona1c73672012-06-14 10:48:04 +00003291 if (!Tok.is(AsmToken::Identifier))
3292 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003293 StringRef IFlagsStr = Tok.getString();
3294
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003295 // An iflags string of "none" is interpreted to mean that none of the AIF
3296 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003297 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003298 if (IFlagsStr != "none") {
3299 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
3300 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
3301 .Case("a", ARM_PROC::A)
3302 .Case("i", ARM_PROC::I)
3303 .Case("f", ARM_PROC::F)
3304 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003305
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003306 // If some specific iflag is already set, it means that some letter is
3307 // present more than once, this is not acceptable.
3308 if (Flag == ~0U || (IFlags & Flag))
3309 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003310
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003311 IFlags |= Flag;
3312 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003313 }
3314
3315 Parser.Lex(); // Eat identifier token.
3316 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
3317 return MatchOperand_Success;
3318}
3319
Jim Grosbach43904292011-07-25 20:14:50 +00003320/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003321ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003322parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003323 SMLoc S = Parser.getTok().getLoc();
3324 const AsmToken &Tok = Parser.getTok();
3325 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3326 StringRef Mask = Tok.getString();
3327
James Molloyacad68d2011-09-28 14:21:38 +00003328 if (isMClass()) {
3329 // See ARMv6-M 10.1.1
Jim Grosbachb84ad4a2012-03-15 21:34:14 +00003330 std::string Name = Mask.lower();
3331 unsigned FlagsVal = StringSwitch<unsigned>(Name)
Kevin Enderby0fd4f3c2012-05-17 22:18:01 +00003332 // Note: in the documentation:
3333 // ARM deprecates using MSR APSR without a _<bits> qualifier as an alias
3334 // for MSR APSR_nzcvq.
3335 // but we do make it an alias here. This is so to get the "mask encoding"
3336 // bits correct on MSR APSR writes.
3337 //
3338 // FIXME: Note the 0xc00 "mask encoding" bits version of the registers
3339 // should really only be allowed when writing a special register. Note
3340 // they get dropped in the MRS instruction reading a special register as
3341 // the SYSm field is only 8 bits.
3342 //
3343 // FIXME: the _g and _nzcvqg versions are only allowed if the processor
3344 // includes the DSP extension but that is not checked.
3345 .Case("apsr", 0x800)
3346 .Case("apsr_nzcvq", 0x800)
3347 .Case("apsr_g", 0x400)
3348 .Case("apsr_nzcvqg", 0xc00)
3349 .Case("iapsr", 0x801)
3350 .Case("iapsr_nzcvq", 0x801)
3351 .Case("iapsr_g", 0x401)
3352 .Case("iapsr_nzcvqg", 0xc01)
3353 .Case("eapsr", 0x802)
3354 .Case("eapsr_nzcvq", 0x802)
3355 .Case("eapsr_g", 0x402)
3356 .Case("eapsr_nzcvqg", 0xc02)
3357 .Case("xpsr", 0x803)
3358 .Case("xpsr_nzcvq", 0x803)
3359 .Case("xpsr_g", 0x403)
3360 .Case("xpsr_nzcvqg", 0xc03)
Kevin Enderbyf49a4092012-06-15 22:14:44 +00003361 .Case("ipsr", 0x805)
3362 .Case("epsr", 0x806)
3363 .Case("iepsr", 0x807)
3364 .Case("msp", 0x808)
3365 .Case("psp", 0x809)
3366 .Case("primask", 0x810)
3367 .Case("basepri", 0x811)
3368 .Case("basepri_max", 0x812)
3369 .Case("faultmask", 0x813)
3370 .Case("control", 0x814)
James Molloyacad68d2011-09-28 14:21:38 +00003371 .Default(~0U);
Jim Grosbach18c8d122011-12-22 17:17:10 +00003372
James Molloyacad68d2011-09-28 14:21:38 +00003373 if (FlagsVal == ~0U)
3374 return MatchOperand_NoMatch;
3375
Kevin Enderbyf49a4092012-06-15 22:14:44 +00003376 if (!hasV7Ops() && FlagsVal >= 0x811 && FlagsVal <= 0x813)
James Molloyacad68d2011-09-28 14:21:38 +00003377 // basepri, basepri_max and faultmask only valid for V7m.
3378 return MatchOperand_NoMatch;
Jim Grosbach18c8d122011-12-22 17:17:10 +00003379
James Molloyacad68d2011-09-28 14:21:38 +00003380 Parser.Lex(); // Eat identifier token.
3381 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3382 return MatchOperand_Success;
3383 }
3384
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003385 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
3386 size_t Start = 0, Next = Mask.find('_');
3387 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00003388 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003389 if (Next != StringRef::npos)
3390 Flags = Mask.slice(Next+1, Mask.size());
3391
3392 // FlagsVal contains the complete mask:
3393 // 3-0: Mask
3394 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3395 unsigned FlagsVal = 0;
3396
3397 if (SpecReg == "apsr") {
3398 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00003399 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003400 .Case("g", 0x4) // same as CPSR_s
3401 .Case("nzcvqg", 0xc) // same as CPSR_fs
3402 .Default(~0U);
3403
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003404 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003405 if (!Flags.empty())
3406 return MatchOperand_NoMatch;
3407 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00003408 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003409 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003410 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Jim Grosbachb657a902012-04-05 03:17:53 +00003411 // cpsr_all is an alias for cpsr_fc, as is plain cpsr.
3412 if (Flags == "all" || Flags == "")
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00003413 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003414 for (int i = 0, e = Flags.size(); i != e; ++i) {
3415 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
3416 .Case("c", 1)
3417 .Case("x", 2)
3418 .Case("s", 4)
3419 .Case("f", 8)
3420 .Default(~0U);
3421
3422 // If some specific flag is already set, it means that some letter is
3423 // present more than once, this is not acceptable.
3424 if (FlagsVal == ~0U || (FlagsVal & Flag))
3425 return MatchOperand_NoMatch;
3426 FlagsVal |= Flag;
3427 }
3428 } else // No match for special register.
3429 return MatchOperand_NoMatch;
3430
Owen Anderson7784f1d2011-10-21 18:43:28 +00003431 // Special register without flags is NOT equivalent to "fc" flags.
3432 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3433 // two lines would enable gas compatibility at the expense of breaking
3434 // round-tripping.
3435 //
3436 // if (!FlagsVal)
3437 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003438
3439 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3440 if (SpecReg == "spsr")
3441 FlagsVal |= 16;
3442
3443 Parser.Lex(); // Eat identifier token.
3444 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3445 return MatchOperand_Success;
3446}
3447
Jim Grosbachf6c05252011-07-21 17:23:04 +00003448ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3449parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3450 int Low, int High) {
3451 const AsmToken &Tok = Parser.getTok();
3452 if (Tok.isNot(AsmToken::Identifier)) {
3453 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3454 return MatchOperand_ParseFail;
3455 }
3456 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00003457 std::string LowerOp = Op.lower();
3458 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00003459 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3460 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3461 return MatchOperand_ParseFail;
3462 }
3463 Parser.Lex(); // Eat shift type token.
3464
3465 // There must be a '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003466 if (Parser.getTok().isNot(AsmToken::Hash) &&
3467 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbachf6c05252011-07-21 17:23:04 +00003468 Error(Parser.getTok().getLoc(), "'#' expected");
3469 return MatchOperand_ParseFail;
3470 }
3471 Parser.Lex(); // Eat hash token.
3472
3473 const MCExpr *ShiftAmount;
3474 SMLoc Loc = Parser.getTok().getLoc();
3475 if (getParser().ParseExpression(ShiftAmount)) {
3476 Error(Loc, "illegal expression");
3477 return MatchOperand_ParseFail;
3478 }
3479 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3480 if (!CE) {
3481 Error(Loc, "constant expression expected");
3482 return MatchOperand_ParseFail;
3483 }
3484 int Val = CE->getValue();
3485 if (Val < Low || Val > High) {
3486 Error(Loc, "immediate value out of range");
3487 return MatchOperand_ParseFail;
3488 }
3489
3490 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3491
3492 return MatchOperand_Success;
3493}
3494
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003495ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3496parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3497 const AsmToken &Tok = Parser.getTok();
3498 SMLoc S = Tok.getLoc();
3499 if (Tok.isNot(AsmToken::Identifier)) {
3500 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3501 return MatchOperand_ParseFail;
3502 }
3503 int Val = StringSwitch<int>(Tok.getString())
3504 .Case("be", 1)
3505 .Case("le", 0)
3506 .Default(-1);
3507 Parser.Lex(); // Eat the token.
3508
3509 if (Val == -1) {
3510 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3511 return MatchOperand_ParseFail;
3512 }
3513 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3514 getContext()),
3515 S, Parser.getTok().getLoc()));
3516 return MatchOperand_Success;
3517}
3518
Jim Grosbach580f4a92011-07-25 22:20:28 +00003519/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3520/// instructions. Legal values are:
3521/// lsl #n 'n' in [0,31]
3522/// asr #n 'n' in [1,32]
3523/// n == 32 encoded as n == 0.
3524ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3525parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3526 const AsmToken &Tok = Parser.getTok();
3527 SMLoc S = Tok.getLoc();
3528 if (Tok.isNot(AsmToken::Identifier)) {
3529 Error(S, "shift operator 'asr' or 'lsl' expected");
3530 return MatchOperand_ParseFail;
3531 }
3532 StringRef ShiftName = Tok.getString();
3533 bool isASR;
3534 if (ShiftName == "lsl" || ShiftName == "LSL")
3535 isASR = false;
3536 else if (ShiftName == "asr" || ShiftName == "ASR")
3537 isASR = true;
3538 else {
3539 Error(S, "shift operator 'asr' or 'lsl' expected");
3540 return MatchOperand_ParseFail;
3541 }
3542 Parser.Lex(); // Eat the operator.
3543
3544 // A '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003545 if (Parser.getTok().isNot(AsmToken::Hash) &&
3546 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach580f4a92011-07-25 22:20:28 +00003547 Error(Parser.getTok().getLoc(), "'#' expected");
3548 return MatchOperand_ParseFail;
3549 }
3550 Parser.Lex(); // Eat hash token.
3551
3552 const MCExpr *ShiftAmount;
3553 SMLoc E = Parser.getTok().getLoc();
3554 if (getParser().ParseExpression(ShiftAmount)) {
3555 Error(E, "malformed shift expression");
3556 return MatchOperand_ParseFail;
3557 }
3558 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3559 if (!CE) {
3560 Error(E, "shift amount must be an immediate");
3561 return MatchOperand_ParseFail;
3562 }
3563
3564 int64_t Val = CE->getValue();
3565 if (isASR) {
3566 // Shift amount must be in [1,32]
3567 if (Val < 1 || Val > 32) {
3568 Error(E, "'asr' shift amount must be in range [1,32]");
3569 return MatchOperand_ParseFail;
3570 }
Owen Anderson0afa0092011-09-26 21:06:22 +00003571 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3572 if (isThumb() && Val == 32) {
3573 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3574 return MatchOperand_ParseFail;
3575 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00003576 if (Val == 32) Val = 0;
3577 } else {
3578 // Shift amount must be in [1,32]
3579 if (Val < 0 || Val > 31) {
3580 Error(E, "'lsr' shift amount must be in range [0,31]");
3581 return MatchOperand_ParseFail;
3582 }
3583 }
3584
3585 E = Parser.getTok().getLoc();
3586 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3587
3588 return MatchOperand_Success;
3589}
3590
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003591/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3592/// of instructions. Legal values are:
3593/// ror #n 'n' in {0, 8, 16, 24}
3594ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3595parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3596 const AsmToken &Tok = Parser.getTok();
3597 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00003598 if (Tok.isNot(AsmToken::Identifier))
3599 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003600 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00003601 if (ShiftName != "ror" && ShiftName != "ROR")
3602 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003603 Parser.Lex(); // Eat the operator.
3604
3605 // A '#' and a rotate amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003606 if (Parser.getTok().isNot(AsmToken::Hash) &&
3607 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003608 Error(Parser.getTok().getLoc(), "'#' expected");
3609 return MatchOperand_ParseFail;
3610 }
3611 Parser.Lex(); // Eat hash token.
3612
3613 const MCExpr *ShiftAmount;
3614 SMLoc E = Parser.getTok().getLoc();
3615 if (getParser().ParseExpression(ShiftAmount)) {
3616 Error(E, "malformed rotate expression");
3617 return MatchOperand_ParseFail;
3618 }
3619 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3620 if (!CE) {
3621 Error(E, "rotate amount must be an immediate");
3622 return MatchOperand_ParseFail;
3623 }
3624
3625 int64_t Val = CE->getValue();
3626 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3627 // normally, zero is represented in asm by omitting the rotate operand
3628 // entirely.
3629 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3630 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3631 return MatchOperand_ParseFail;
3632 }
3633
3634 E = Parser.getTok().getLoc();
3635 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3636
3637 return MatchOperand_Success;
3638}
3639
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003640ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3641parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3642 SMLoc S = Parser.getTok().getLoc();
3643 // The bitfield descriptor is really two operands, the LSB and the width.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003644 if (Parser.getTok().isNot(AsmToken::Hash) &&
3645 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003646 Error(Parser.getTok().getLoc(), "'#' expected");
3647 return MatchOperand_ParseFail;
3648 }
3649 Parser.Lex(); // Eat hash token.
3650
3651 const MCExpr *LSBExpr;
3652 SMLoc E = Parser.getTok().getLoc();
3653 if (getParser().ParseExpression(LSBExpr)) {
3654 Error(E, "malformed immediate expression");
3655 return MatchOperand_ParseFail;
3656 }
3657 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3658 if (!CE) {
3659 Error(E, "'lsb' operand must be an immediate");
3660 return MatchOperand_ParseFail;
3661 }
3662
3663 int64_t LSB = CE->getValue();
3664 // The LSB must be in the range [0,31]
3665 if (LSB < 0 || LSB > 31) {
3666 Error(E, "'lsb' operand must be in the range [0,31]");
3667 return MatchOperand_ParseFail;
3668 }
3669 E = Parser.getTok().getLoc();
3670
3671 // Expect another immediate operand.
3672 if (Parser.getTok().isNot(AsmToken::Comma)) {
3673 Error(Parser.getTok().getLoc(), "too few operands");
3674 return MatchOperand_ParseFail;
3675 }
3676 Parser.Lex(); // Eat hash token.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003677 if (Parser.getTok().isNot(AsmToken::Hash) &&
3678 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003679 Error(Parser.getTok().getLoc(), "'#' expected");
3680 return MatchOperand_ParseFail;
3681 }
3682 Parser.Lex(); // Eat hash token.
3683
3684 const MCExpr *WidthExpr;
3685 if (getParser().ParseExpression(WidthExpr)) {
3686 Error(E, "malformed immediate expression");
3687 return MatchOperand_ParseFail;
3688 }
3689 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3690 if (!CE) {
3691 Error(E, "'width' operand must be an immediate");
3692 return MatchOperand_ParseFail;
3693 }
3694
3695 int64_t Width = CE->getValue();
3696 // The LSB must be in the range [1,32-lsb]
3697 if (Width < 1 || Width > 32 - LSB) {
3698 Error(E, "'width' operand must be in the range [1,32-lsb]");
3699 return MatchOperand_ParseFail;
3700 }
3701 E = Parser.getTok().getLoc();
3702
3703 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3704
3705 return MatchOperand_Success;
3706}
3707
Jim Grosbach7ce05792011-08-03 23:50:40 +00003708ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3709parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3710 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003711 // postidx_reg := '+' register {, shift}
3712 // | '-' register {, shift}
3713 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003714
3715 // This method must return MatchOperand_NoMatch without consuming any tokens
3716 // in the case where there is no match, as other alternatives take other
3717 // parse methods.
3718 AsmToken Tok = Parser.getTok();
3719 SMLoc S = Tok.getLoc();
3720 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003721 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003722 int Reg = -1;
3723 if (Tok.is(AsmToken::Plus)) {
3724 Parser.Lex(); // Eat the '+' token.
3725 haveEaten = true;
3726 } else if (Tok.is(AsmToken::Minus)) {
3727 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003728 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003729 haveEaten = true;
3730 }
3731 if (Parser.getTok().is(AsmToken::Identifier))
3732 Reg = tryParseRegister();
3733 if (Reg == -1) {
3734 if (!haveEaten)
3735 return MatchOperand_NoMatch;
3736 Error(Parser.getTok().getLoc(), "register expected");
3737 return MatchOperand_ParseFail;
3738 }
3739 SMLoc E = Parser.getTok().getLoc();
3740
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003741 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3742 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003743 if (Parser.getTok().is(AsmToken::Comma)) {
3744 Parser.Lex(); // Eat the ','.
3745 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3746 return MatchOperand_ParseFail;
3747 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003748
3749 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3750 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003751
3752 return MatchOperand_Success;
3753}
3754
Jim Grosbach251bf252011-08-10 21:56:18 +00003755ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3756parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3757 // Check for a post-index addressing register operand. Specifically:
3758 // am3offset := '+' register
3759 // | '-' register
3760 // | register
3761 // | # imm
3762 // | # + imm
3763 // | # - imm
3764
3765 // This method must return MatchOperand_NoMatch without consuming any tokens
3766 // in the case where there is no match, as other alternatives take other
3767 // parse methods.
3768 AsmToken Tok = Parser.getTok();
3769 SMLoc S = Tok.getLoc();
3770
3771 // Do immediates first, as we always parse those if we have a '#'.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003772 if (Parser.getTok().is(AsmToken::Hash) ||
3773 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach251bf252011-08-10 21:56:18 +00003774 Parser.Lex(); // Eat the '#'.
3775 // Explicitly look for a '-', as we need to encode negative zero
3776 // differently.
3777 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3778 const MCExpr *Offset;
3779 if (getParser().ParseExpression(Offset))
3780 return MatchOperand_ParseFail;
3781 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3782 if (!CE) {
3783 Error(S, "constant expression expected");
3784 return MatchOperand_ParseFail;
3785 }
3786 SMLoc E = Tok.getLoc();
3787 // Negative zero is encoded as the flag value INT32_MIN.
3788 int32_t Val = CE->getValue();
3789 if (isNegative && Val == 0)
3790 Val = INT32_MIN;
3791
3792 Operands.push_back(
3793 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3794
3795 return MatchOperand_Success;
3796 }
3797
3798
3799 bool haveEaten = false;
3800 bool isAdd = true;
3801 int Reg = -1;
3802 if (Tok.is(AsmToken::Plus)) {
3803 Parser.Lex(); // Eat the '+' token.
3804 haveEaten = true;
3805 } else if (Tok.is(AsmToken::Minus)) {
3806 Parser.Lex(); // Eat the '-' token.
3807 isAdd = false;
3808 haveEaten = true;
3809 }
3810 if (Parser.getTok().is(AsmToken::Identifier))
3811 Reg = tryParseRegister();
3812 if (Reg == -1) {
3813 if (!haveEaten)
3814 return MatchOperand_NoMatch;
3815 Error(Parser.getTok().getLoc(), "register expected");
3816 return MatchOperand_ParseFail;
3817 }
3818 SMLoc E = Parser.getTok().getLoc();
3819
3820 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3821 0, S, E));
3822
3823 return MatchOperand_Success;
3824}
3825
Jim Grosbacha77295d2011-09-08 22:07:06 +00003826/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3827/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3828/// when they refer multiple MIOperands inside a single one.
3829bool ARMAsmParser::
3830cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3831 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3832 // Rt, Rt2
3833 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3834 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3835 // Create a writeback register dummy placeholder.
3836 Inst.addOperand(MCOperand::CreateReg(0));
3837 // addr
3838 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3839 // pred
3840 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3841 return true;
3842}
3843
3844/// cvtT2StrdPre - 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::
3848cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3849 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3850 // Create a writeback register dummy placeholder.
3851 Inst.addOperand(MCOperand::CreateReg(0));
3852 // Rt, Rt2
3853 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3854 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3855 // addr
3856 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3857 // pred
3858 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3859 return true;
3860}
3861
Jim Grosbacheeec0252011-09-08 00:39:19 +00003862/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3863/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3864/// when they refer multiple MIOperands inside a single one.
3865bool ARMAsmParser::
3866cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3867 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3868 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3869
3870 // Create a writeback register dummy placeholder.
3871 Inst.addOperand(MCOperand::CreateImm(0));
3872
3873 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3874 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3875 return true;
3876}
3877
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003878/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3879/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3880/// when they refer multiple MIOperands inside a single one.
3881bool ARMAsmParser::
3882cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3883 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3884 // Create a writeback register dummy placeholder.
3885 Inst.addOperand(MCOperand::CreateImm(0));
3886 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3887 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3888 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3889 return true;
3890}
3891
Jim Grosbach1355cf12011-07-26 17:10:22 +00003892/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003893/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3894/// when they refer multiple MIOperands inside a single one.
3895bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003896cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003897 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3898 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3899
3900 // Create a writeback register dummy placeholder.
3901 Inst.addOperand(MCOperand::CreateImm(0));
3902
Jim Grosbach7ce05792011-08-03 23:50:40 +00003903 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003904 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3905 return true;
3906}
3907
Owen Anderson9ab0f252011-08-26 20:43:14 +00003908/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3909/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3910/// when they refer multiple MIOperands inside a single one.
3911bool ARMAsmParser::
3912cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3913 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3914 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3915
3916 // Create a writeback register dummy placeholder.
3917 Inst.addOperand(MCOperand::CreateImm(0));
3918
3919 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3920 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3921 return true;
3922}
3923
3924
Jim Grosbach548340c2011-08-11 19:22:40 +00003925/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3926/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3927/// when they refer multiple MIOperands inside a single one.
3928bool ARMAsmParser::
3929cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3930 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3931 // Create a writeback register dummy placeholder.
3932 Inst.addOperand(MCOperand::CreateImm(0));
3933 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3934 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3935 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3936 return true;
3937}
3938
Jim Grosbach1355cf12011-07-26 17:10:22 +00003939/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003940/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3941/// when they refer multiple MIOperands inside a single one.
3942bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003943cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003944 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3945 // Create a writeback register dummy placeholder.
3946 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003947 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3948 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3949 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003950 return true;
3951}
3952
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003953/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3954/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3955/// when they refer multiple MIOperands inside a single one.
3956bool ARMAsmParser::
3957cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3958 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3959 // Create a writeback register dummy placeholder.
3960 Inst.addOperand(MCOperand::CreateImm(0));
3961 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3962 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3963 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3964 return true;
3965}
3966
Jim Grosbach7ce05792011-08-03 23:50:40 +00003967/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3968/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3969/// when they refer multiple MIOperands inside a single one.
3970bool ARMAsmParser::
3971cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3972 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3973 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003974 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003975 // Create a writeback register dummy placeholder.
3976 Inst.addOperand(MCOperand::CreateImm(0));
3977 // addr
3978 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3979 // offset
3980 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3981 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003982 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3983 return true;
3984}
3985
Jim Grosbach7ce05792011-08-03 23:50:40 +00003986/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003987/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3988/// when they refer multiple MIOperands inside a single one.
3989bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003990cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3991 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3992 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003993 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003994 // Create a writeback register dummy placeholder.
3995 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003996 // addr
3997 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3998 // offset
3999 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
4000 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00004001 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4002 return true;
4003}
4004
Jim Grosbach7ce05792011-08-03 23:50:40 +00004005/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00004006/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4007/// when they refer multiple MIOperands inside a single one.
4008bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00004009cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
4010 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00004011 // Create a writeback register dummy placeholder.
4012 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00004013 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00004014 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00004015 // addr
4016 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
4017 // offset
4018 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
4019 // pred
4020 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4021 return true;
4022}
4023
4024/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
4025/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4026/// when they refer multiple MIOperands inside a single one.
4027bool ARMAsmParser::
4028cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
4029 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4030 // Create a writeback register dummy placeholder.
4031 Inst.addOperand(MCOperand::CreateImm(0));
4032 // Rt
4033 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
4034 // addr
4035 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
4036 // offset
4037 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
4038 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00004039 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4040 return true;
4041}
4042
Jim Grosbach2fd2b872011-08-10 20:29:19 +00004043/// cvtLdrdPre - Convert parsed operands to MCInst.
4044/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4045/// when they refer multiple MIOperands inside a single one.
4046bool ARMAsmParser::
4047cvtLdrdPre(MCInst &Inst, unsigned Opcode,
4048 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4049 // Rt, Rt2
4050 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
4051 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
4052 // Create a writeback register dummy placeholder.
4053 Inst.addOperand(MCOperand::CreateImm(0));
4054 // addr
4055 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
4056 // pred
4057 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4058 return true;
4059}
4060
Jim Grosbach14605d12011-08-11 20:28:23 +00004061/// cvtStrdPre - Convert parsed operands to MCInst.
4062/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4063/// when they refer multiple MIOperands inside a single one.
4064bool ARMAsmParser::
4065cvtStrdPre(MCInst &Inst, unsigned Opcode,
4066 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4067 // Create a writeback register dummy placeholder.
4068 Inst.addOperand(MCOperand::CreateImm(0));
4069 // Rt, Rt2
4070 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
4071 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
4072 // addr
4073 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
4074 // pred
4075 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4076 return true;
4077}
4078
Jim Grosbach623a4542011-08-10 22:42:16 +00004079/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
4080/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4081/// when they refer multiple MIOperands inside a single one.
4082bool ARMAsmParser::
4083cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
4084 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4085 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
4086 // Create a writeback register dummy placeholder.
4087 Inst.addOperand(MCOperand::CreateImm(0));
4088 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
4089 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4090 return true;
4091}
4092
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004093/// cvtThumbMultiple- Convert parsed operands to MCInst.
4094/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4095/// when they refer multiple MIOperands inside a single one.
4096bool ARMAsmParser::
4097cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
4098 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4099 // The second source operand must be the same register as the destination
4100 // operand.
4101 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00004102 (((ARMOperand*)Operands[3])->getReg() !=
4103 ((ARMOperand*)Operands[5])->getReg()) &&
4104 (((ARMOperand*)Operands[3])->getReg() !=
4105 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004106 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00004107 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004108 return false;
4109 }
4110 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
4111 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach1b332862011-11-10 22:10:12 +00004112 // If we have a three-operand form, make sure to set Rn to be the operand
4113 // that isn't the same as Rd.
4114 unsigned RegOp = 4;
4115 if (Operands.size() == 6 &&
4116 ((ARMOperand*)Operands[4])->getReg() ==
4117 ((ARMOperand*)Operands[3])->getReg())
4118 RegOp = 5;
4119 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
4120 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004121 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
4122
4123 return true;
4124}
Jim Grosbach623a4542011-08-10 22:42:16 +00004125
Jim Grosbach12431322011-10-24 22:16:58 +00004126bool ARMAsmParser::
4127cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
4128 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4129 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004130 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00004131 // Create a writeback register dummy placeholder.
4132 Inst.addOperand(MCOperand::CreateImm(0));
4133 // Vn
4134 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4135 // pred
4136 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4137 return true;
4138}
4139
4140bool ARMAsmParser::
4141cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
4142 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4143 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004144 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00004145 // Create a writeback register dummy placeholder.
4146 Inst.addOperand(MCOperand::CreateImm(0));
4147 // Vn
4148 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4149 // Vm
4150 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4151 // pred
4152 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4153 return true;
4154}
4155
Jim Grosbach4334e032011-10-31 21:50:31 +00004156bool ARMAsmParser::
4157cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
4158 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4159 // Create a writeback register dummy placeholder.
4160 Inst.addOperand(MCOperand::CreateImm(0));
4161 // Vn
4162 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4163 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004164 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00004165 // pred
4166 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4167 return true;
4168}
4169
4170bool ARMAsmParser::
4171cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
4172 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4173 // Create a writeback register dummy placeholder.
4174 Inst.addOperand(MCOperand::CreateImm(0));
4175 // Vn
4176 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4177 // Vm
4178 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4179 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004180 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00004181 // pred
4182 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4183 return true;
4184}
4185
Bill Wendlinge7176102010-11-06 22:36:58 +00004186/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004187/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00004188bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00004189parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00004190 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00004191 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00004192 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00004193 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004194 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004195
Sean Callanan18b83232010-01-19 21:44:56 +00004196 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00004197 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00004198 if (BaseRegNum == -1)
4199 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004200
Daniel Dunbar05710932011-01-18 05:34:17 +00004201 // The next token must either be a comma or a closing bracket.
4202 const AsmToken &Tok = Parser.getTok();
4203 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004204 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00004205
Jim Grosbach7ce05792011-08-03 23:50:40 +00004206 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00004207 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004208 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004209
Jim Grosbach7ce05792011-08-03 23:50:40 +00004210 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004211 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00004212
Jim Grosbachfb12f352011-09-19 18:42:21 +00004213 // If there's a pre-indexing writeback marker, '!', just add it as a token
4214 // operand. It's rather odd, but syntactically valid.
4215 if (Parser.getTok().is(AsmToken::Exclaim)) {
4216 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4217 Parser.Lex(); // Eat the '!'.
4218 }
4219
Jim Grosbach7ce05792011-08-03 23:50:40 +00004220 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004221 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004222
Jim Grosbach7ce05792011-08-03 23:50:40 +00004223 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
4224 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004225
Jim Grosbach57dcb852011-10-11 17:29:55 +00004226 // If we have a ':', it's an alignment specifier.
4227 if (Parser.getTok().is(AsmToken::Colon)) {
4228 Parser.Lex(); // Eat the ':'.
4229 E = Parser.getTok().getLoc();
4230
4231 const MCExpr *Expr;
4232 if (getParser().ParseExpression(Expr))
4233 return true;
4234
4235 // The expression has to be a constant. Memory references with relocations
4236 // don't come through here, as they use the <label> forms of the relevant
4237 // instructions.
4238 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4239 if (!CE)
4240 return Error (E, "constant expression expected");
4241
4242 unsigned Align = 0;
4243 switch (CE->getValue()) {
4244 default:
Jim Grosbacheeaf1c12011-12-19 18:31:43 +00004245 return Error(E,
4246 "alignment specifier must be 16, 32, 64, 128, or 256 bits");
4247 case 16: Align = 2; break;
4248 case 32: Align = 4; break;
Jim Grosbach57dcb852011-10-11 17:29:55 +00004249 case 64: Align = 8; break;
4250 case 128: Align = 16; break;
4251 case 256: Align = 32; break;
4252 }
4253
4254 // Now we should have the closing ']'
4255 E = Parser.getTok().getLoc();
4256 if (Parser.getTok().isNot(AsmToken::RBrac))
4257 return Error(E, "']' expected");
4258 Parser.Lex(); // Eat right bracket token.
4259
4260 // Don't worry about range checking the value here. That's handled by
4261 // the is*() predicates.
4262 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
4263 ARM_AM::no_shift, 0, Align,
4264 false, S, E));
4265
4266 // If there's a pre-indexing writeback marker, '!', just add it as a token
4267 // operand.
4268 if (Parser.getTok().is(AsmToken::Exclaim)) {
4269 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4270 Parser.Lex(); // Eat the '!'.
4271 }
4272
4273 return false;
4274 }
4275
4276 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004277 // offset. Be friendly and also accept a plain integer (without a leading
4278 // hash) for gas compatibility.
4279 if (Parser.getTok().is(AsmToken::Hash) ||
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004280 Parser.getTok().is(AsmToken::Dollar) ||
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004281 Parser.getTok().is(AsmToken::Integer)) {
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004282 if (Parser.getTok().isNot(AsmToken::Integer))
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004283 Parser.Lex(); // Eat the '#'.
Jim Grosbach7ce05792011-08-03 23:50:40 +00004284 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004285
Owen Anderson0da10cf2011-08-29 19:36:44 +00004286 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00004287 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004288 if (getParser().ParseExpression(Offset))
4289 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004290
4291 // The expression has to be a constant. Memory references with relocations
4292 // don't come through here, as they use the <label> forms of the relevant
4293 // instructions.
4294 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
4295 if (!CE)
4296 return Error (E, "constant expression expected");
4297
Owen Anderson0da10cf2011-08-29 19:36:44 +00004298 // If the constant was #-0, represent it as INT32_MIN.
4299 int32_t Val = CE->getValue();
4300 if (isNegative && Val == 0)
4301 CE = MCConstantExpr::Create(INT32_MIN, getContext());
4302
Jim Grosbach7ce05792011-08-03 23:50:40 +00004303 // Now we should have the closing ']'
4304 E = Parser.getTok().getLoc();
4305 if (Parser.getTok().isNot(AsmToken::RBrac))
4306 return Error(E, "']' expected");
4307 Parser.Lex(); // Eat right bracket token.
4308
4309 // Don't worry about range checking the value here. That's handled by
4310 // the is*() predicates.
4311 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004312 ARM_AM::no_shift, 0, 0,
4313 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00004314
4315 // If there's a pre-indexing writeback marker, '!', just add it as a token
4316 // operand.
4317 if (Parser.getTok().is(AsmToken::Exclaim)) {
4318 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4319 Parser.Lex(); // Eat the '!'.
4320 }
4321
4322 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004323 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004324
4325 // The register offset is optionally preceded by a '+' or '-'
4326 bool isNegative = false;
4327 if (Parser.getTok().is(AsmToken::Minus)) {
4328 isNegative = true;
4329 Parser.Lex(); // Eat the '-'.
4330 } else if (Parser.getTok().is(AsmToken::Plus)) {
4331 // Nothing to do.
4332 Parser.Lex(); // Eat the '+'.
4333 }
4334
4335 E = Parser.getTok().getLoc();
4336 int OffsetRegNum = tryParseRegister();
4337 if (OffsetRegNum == -1)
4338 return Error(E, "register expected");
4339
4340 // If there's a shift operator, handle it.
4341 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004342 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004343 if (Parser.getTok().is(AsmToken::Comma)) {
4344 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004345 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004346 return true;
4347 }
4348
4349 // Now we should have the closing ']'
4350 E = Parser.getTok().getLoc();
4351 if (Parser.getTok().isNot(AsmToken::RBrac))
4352 return Error(E, "']' expected");
4353 Parser.Lex(); // Eat right bracket token.
4354
4355 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004356 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00004357 S, E));
4358
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00004359 // If there's a pre-indexing writeback marker, '!', just add it as a token
4360 // operand.
4361 if (Parser.getTok().is(AsmToken::Exclaim)) {
4362 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4363 Parser.Lex(); // Eat the '!'.
4364 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004365
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004366 return false;
4367}
4368
Jim Grosbach7ce05792011-08-03 23:50:40 +00004369/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004370/// ( lsl | lsr | asr | ror ) , # shift_amount
4371/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00004372/// return true if it parses a shift otherwise it returns false.
4373bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
4374 unsigned &Amount) {
4375 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00004376 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004377 if (Tok.isNot(AsmToken::Identifier))
4378 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00004379 StringRef ShiftName = Tok.getString();
Jim Grosbachaf4edea2011-12-07 23:40:58 +00004380 if (ShiftName == "lsl" || ShiftName == "LSL" ||
4381 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson00828302011-03-18 22:50:18 +00004382 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004383 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00004384 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004385 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00004386 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004387 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00004388 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004389 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00004390 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004391 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00004392 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00004393 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004394
Jim Grosbach7ce05792011-08-03 23:50:40 +00004395 // rrx stands alone.
4396 Amount = 0;
4397 if (St != ARM_AM::rrx) {
4398 Loc = Parser.getTok().getLoc();
4399 // A '#' and a shift amount.
4400 const AsmToken &HashTok = Parser.getTok();
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004401 if (HashTok.isNot(AsmToken::Hash) &&
4402 HashTok.isNot(AsmToken::Dollar))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004403 return Error(HashTok.getLoc(), "'#' expected");
4404 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004405
Jim Grosbach7ce05792011-08-03 23:50:40 +00004406 const MCExpr *Expr;
4407 if (getParser().ParseExpression(Expr))
4408 return true;
4409 // Range check the immediate.
4410 // lsl, ror: 0 <= imm <= 31
4411 // lsr, asr: 0 <= imm <= 32
4412 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4413 if (!CE)
4414 return Error(Loc, "shift amount must be an immediate");
4415 int64_t Imm = CE->getValue();
4416 if (Imm < 0 ||
4417 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4418 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4419 return Error(Loc, "immediate shift value out of range");
4420 Amount = Imm;
4421 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004422
4423 return false;
4424}
4425
Jim Grosbach9d390362011-10-03 23:38:36 +00004426/// parseFPImm - A floating point immediate expression operand.
4427ARMAsmParser::OperandMatchResultTy ARMAsmParser::
4428parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach51222d12012-01-20 18:09:51 +00004429 // Anything that can accept a floating point constant as an operand
4430 // needs to go through here, as the regular ParseExpression is
4431 // integer only.
4432 //
4433 // This routine still creates a generic Immediate operand, containing
4434 // a bitcast of the 64-bit floating point value. The various operands
4435 // that accept floats can check whether the value is valid for them
4436 // via the standard is*() predicates.
4437
Jim Grosbach9d390362011-10-03 23:38:36 +00004438 SMLoc S = Parser.getTok().getLoc();
4439
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004440 if (Parser.getTok().isNot(AsmToken::Hash) &&
4441 Parser.getTok().isNot(AsmToken::Dollar))
Jim Grosbach9d390362011-10-03 23:38:36 +00004442 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00004443
4444 // Disambiguate the VMOV forms that can accept an FP immediate.
4445 // vmov.f32 <sreg>, #imm
4446 // vmov.f64 <dreg>, #imm
4447 // vmov.f32 <dreg>, #imm @ vector f32x2
4448 // vmov.f32 <qreg>, #imm @ vector f32x4
4449 //
4450 // There are also the NEON VMOV instructions which expect an
4451 // integer constant. Make sure we don't try to parse an FPImm
4452 // for these:
4453 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4454 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4455 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4456 TyOp->getToken() != ".f64"))
4457 return MatchOperand_NoMatch;
4458
Jim Grosbach9d390362011-10-03 23:38:36 +00004459 Parser.Lex(); // Eat the '#'.
4460
4461 // Handle negation, as that still comes through as a separate token.
4462 bool isNegative = false;
4463 if (Parser.getTok().is(AsmToken::Minus)) {
4464 isNegative = true;
4465 Parser.Lex();
4466 }
4467 const AsmToken &Tok = Parser.getTok();
Jim Grosbachae69f702012-01-19 02:47:30 +00004468 SMLoc Loc = Tok.getLoc();
Jim Grosbach9d390362011-10-03 23:38:36 +00004469 if (Tok.is(AsmToken::Real)) {
Jim Grosbach51222d12012-01-20 18:09:51 +00004470 APFloat RealVal(APFloat::IEEEsingle, Tok.getString());
Jim Grosbach9d390362011-10-03 23:38:36 +00004471 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4472 // If we had a '-' in front, toggle the sign bit.
Jim Grosbach51222d12012-01-20 18:09:51 +00004473 IntVal ^= (uint64_t)isNegative << 31;
Jim Grosbach9d390362011-10-03 23:38:36 +00004474 Parser.Lex(); // Eat the token.
Jim Grosbach51222d12012-01-20 18:09:51 +00004475 Operands.push_back(ARMOperand::CreateImm(
4476 MCConstantExpr::Create(IntVal, getContext()),
4477 S, Parser.getTok().getLoc()));
Jim Grosbach9d390362011-10-03 23:38:36 +00004478 return MatchOperand_Success;
4479 }
Jim Grosbach51222d12012-01-20 18:09:51 +00004480 // Also handle plain integers. Instructions which allow floating point
4481 // immediates also allow a raw encoded 8-bit value.
Jim Grosbach9d390362011-10-03 23:38:36 +00004482 if (Tok.is(AsmToken::Integer)) {
4483 int64_t Val = Tok.getIntVal();
4484 Parser.Lex(); // Eat the token.
4485 if (Val > 255 || Val < 0) {
Jim Grosbachae69f702012-01-19 02:47:30 +00004486 Error(Loc, "encoded floating point value out of range");
Jim Grosbach9d390362011-10-03 23:38:36 +00004487 return MatchOperand_ParseFail;
4488 }
Jim Grosbach51222d12012-01-20 18:09:51 +00004489 double RealVal = ARM_AM::getFPImmFloat(Val);
4490 Val = APFloat(APFloat::IEEEdouble, RealVal).bitcastToAPInt().getZExtValue();
4491 Operands.push_back(ARMOperand::CreateImm(
4492 MCConstantExpr::Create(Val, getContext()), S,
4493 Parser.getTok().getLoc()));
Jim Grosbach9d390362011-10-03 23:38:36 +00004494 return MatchOperand_Success;
4495 }
4496
Jim Grosbachae69f702012-01-19 02:47:30 +00004497 Error(Loc, "invalid floating point immediate");
Jim Grosbach9d390362011-10-03 23:38:36 +00004498 return MatchOperand_ParseFail;
4499}
Jim Grosbach51222d12012-01-20 18:09:51 +00004500
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004501/// Parse a arm instruction operand. For now this parses the operand regardless
4502/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004503bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004504 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00004505 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004506
4507 // Check if the current operand has a custom associated parser, if so, try to
4508 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00004509 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4510 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004511 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00004512 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4513 // there was a match, but an error occurred, in which case, just return that
4514 // the operand parsing failed.
4515 if (ResTy == MatchOperand_ParseFail)
4516 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004517
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004518 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00004519 default:
4520 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00004521 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00004522 case AsmToken::Identifier: {
Jim Grosbach1355cf12011-07-26 17:10:22 +00004523 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00004524 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00004525 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00004526 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00004527 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00004528 else if (Res == -1) // irrecoverable error
4529 return true;
Jim Grosbach3cbe43f2011-12-20 22:26:38 +00004530 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbachb84ad4a2012-03-15 21:34:14 +00004531 if (Mnemonic == "vmrs" &&
4532 Parser.getTok().getString().equals_lower("apsr_nzcv")) {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004533 S = Parser.getTok().getLoc();
4534 Parser.Lex();
Jim Grosbachb84ad4a2012-03-15 21:34:14 +00004535 Operands.push_back(ARMOperand::CreateToken("APSR_nzcv", S));
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004536 return false;
4537 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00004538
4539 // Fall though for the Identifier case that is not a register or a
4540 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00004541 }
Jim Grosbach758a5192011-10-26 21:14:08 +00004542 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00004543 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00004544 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00004545 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00004546 // This was not a register so parse other operands that start with an
4547 // identifier (like labels) as expressions and create them as immediates.
4548 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00004549 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00004550 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004551 return true;
Sean Callanan76264762010-04-02 22:27:05 +00004552 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004553 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4554 return false;
4555 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004556 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004557 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00004558 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004559 return parseRegisterList(Operands);
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004560 case AsmToken::Dollar:
Owen Anderson63553c72011-08-29 17:17:09 +00004561 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00004562 // #42 -> immediate.
Sean Callanan76264762010-04-02 22:27:05 +00004563 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004564 Parser.Lex();
Jim Grosbachb8768dc2012-04-16 21:18:46 +00004565
4566 if (Parser.getTok().isNot(AsmToken::Colon)) {
4567 bool isNegative = Parser.getTok().is(AsmToken::Minus);
4568 const MCExpr *ImmVal;
4569 if (getParser().ParseExpression(ImmVal))
4570 return true;
4571 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
4572 if (CE) {
4573 int32_t Val = CE->getValue();
4574 if (isNegative && Val == 0)
4575 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
4576 }
4577 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4578 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4579 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00004580 }
Jim Grosbachb8768dc2012-04-16 21:18:46 +00004581 // w/ a ':' after the '#', it's just like a plain ':'.
4582 // FALLTHROUGH
Owen Anderson63553c72011-08-29 17:17:09 +00004583 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004584 case AsmToken::Colon: {
4585 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00004586 // FIXME: Check it's an expression prefix,
4587 // e.g. (FOO - :lower16:BAR) isn't legal.
4588 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004589 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004590 return true;
4591
Evan Cheng75972122011-01-13 07:58:56 +00004592 const MCExpr *SubExprVal;
4593 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004594 return true;
4595
Evan Cheng75972122011-01-13 07:58:56 +00004596 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4597 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00004598 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00004599 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00004600 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004601 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004602 }
4603}
4604
Jim Grosbach1355cf12011-07-26 17:10:22 +00004605// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00004606// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004607bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00004608 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004609
4610 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00004611 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00004612 Parser.Lex(); // Eat ':'
4613
4614 if (getLexer().isNot(AsmToken::Identifier)) {
4615 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4616 return true;
4617 }
4618
4619 StringRef IDVal = Parser.getTok().getIdentifier();
4620 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00004621 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004622 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00004623 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004624 } else {
4625 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4626 return true;
4627 }
4628 Parser.Lex();
4629
4630 if (getLexer().isNot(AsmToken::Colon)) {
4631 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4632 return true;
4633 }
4634 Parser.Lex(); // Eat the last ':'
4635 return false;
4636}
4637
Daniel Dunbar352e1482011-01-11 15:59:50 +00004638/// \brief Given a mnemonic, split out possible predication code and carry
4639/// setting letters to form a canonical mnemonic and flags.
4640//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004641// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00004642// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004643StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00004644 unsigned &PredicationCode,
4645 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004646 unsigned &ProcessorIMod,
4647 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004648 PredicationCode = ARMCC::AL;
4649 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004650 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004651
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004652 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00004653 //
4654 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00004655 if ((Mnemonic == "movs" && isThumb()) ||
4656 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4657 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4658 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4659 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4660 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4661 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
Jim Grosbach68490192011-12-19 19:43:50 +00004662 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" ||
4663 Mnemonic == "fmuls")
Daniel Dunbar352e1482011-01-11 15:59:50 +00004664 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00004665
Jim Grosbach3f00e312011-07-11 17:09:57 +00004666 // First, split out any predication code. Ignore mnemonics we know aren't
4667 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00004668 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00004669 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00004670 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00004671 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00004672 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4673 .Case("eq", ARMCC::EQ)
4674 .Case("ne", ARMCC::NE)
4675 .Case("hs", ARMCC::HS)
4676 .Case("cs", ARMCC::HS)
4677 .Case("lo", ARMCC::LO)
4678 .Case("cc", ARMCC::LO)
4679 .Case("mi", ARMCC::MI)
4680 .Case("pl", ARMCC::PL)
4681 .Case("vs", ARMCC::VS)
4682 .Case("vc", ARMCC::VC)
4683 .Case("hi", ARMCC::HI)
4684 .Case("ls", ARMCC::LS)
4685 .Case("ge", ARMCC::GE)
4686 .Case("lt", ARMCC::LT)
4687 .Case("gt", ARMCC::GT)
4688 .Case("le", ARMCC::LE)
4689 .Case("al", ARMCC::AL)
4690 .Default(~0U);
4691 if (CC != ~0U) {
4692 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4693 PredicationCode = CC;
4694 }
Bill Wendling52925b62010-10-29 23:50:21 +00004695 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004696
Daniel Dunbar352e1482011-01-11 15:59:50 +00004697 // Next, determine if we have a carry setting bit. We explicitly ignore all
4698 // the instructions we know end in 's'.
4699 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00004700 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00004701 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4702 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4703 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach67ca1ad2011-12-08 00:49:29 +00004704 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach48171e72011-12-10 00:01:02 +00004705 Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
Jim Grosbach9c397892011-12-19 19:02:41 +00004706 Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" ||
Jim Grosbach6357cae2012-03-15 20:48:18 +00004707 Mnemonic == "fmuls" || Mnemonic == "fcmps" || Mnemonic == "fcmpzs" ||
Evan Cheng82509e52012-04-11 00:13:00 +00004708 Mnemonic == "vfms" || Mnemonic == "vfnms" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00004709 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004710 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4711 CarrySetting = true;
4712 }
4713
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004714 // The "cps" instruction can have a interrupt mode operand which is glued into
4715 // the mnemonic. Check if this is the case, split it and parse the imod op
4716 if (Mnemonic.startswith("cps")) {
4717 // Split out any imod code.
4718 unsigned IMod =
4719 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4720 .Case("ie", ARM_PROC::IE)
4721 .Case("id", ARM_PROC::ID)
4722 .Default(~0U);
4723 if (IMod != ~0U) {
4724 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4725 ProcessorIMod = IMod;
4726 }
4727 }
4728
Jim Grosbach89df9962011-08-26 21:43:41 +00004729 // The "it" instruction has the condition mask on the end of the mnemonic.
4730 if (Mnemonic.startswith("it")) {
4731 ITMask = Mnemonic.slice(2, Mnemonic.size());
4732 Mnemonic = Mnemonic.slice(0, 2);
4733 }
4734
Daniel Dunbar352e1482011-01-11 15:59:50 +00004735 return Mnemonic;
4736}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004737
4738/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4739/// inclusion of carry set or predication code operands.
4740//
4741// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004742void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00004743getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004744 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004745 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4746 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004747 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004748 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004749 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004750 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004751 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Evan Cheng82509e52012-04-11 00:13:00 +00004752 Mnemonic == "vfm" || Mnemonic == "vfnm" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004753 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004754 Mnemonic == "mla" || Mnemonic == "smlal" ||
4755 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004756 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004757 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004758 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004759
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004760 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4761 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4762 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4763 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004764 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4765 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004766 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004767 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4768 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4769 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004770 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4771 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004772 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004773 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004774 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004775 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004776
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004777 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004778 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004779 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004780 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004781 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004782}
4783
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004784bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4785 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004786 // FIXME: This is all horribly hacky. We really need a better way to deal
4787 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004788
4789 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4790 // another does not. Specifically, the MOVW instruction does not. So we
4791 // special case it here and remove the defaulted (non-setting) cc_out
4792 // operand if that's the instruction we're trying to match.
4793 //
4794 // We do this as post-processing of the explicit operands rather than just
4795 // conditionally adding the cc_out in the first place because we need
4796 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004797 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004798 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4799 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4800 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4801 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004802
4803 // Register-register 'add' for thumb does not have a cc_out operand
4804 // when there are only two register operands.
4805 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4806 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4807 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4808 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4809 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004810 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004811 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4812 // have to check the immediate range here since Thumb2 has a variant
4813 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004814 if (((isThumb() && Mnemonic == "add") ||
4815 (isThumbTwo() && Mnemonic == "sub")) &&
4816 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004817 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4818 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4819 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004820 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
Jim Grosbacha23ecc22012-04-10 17:31:55 +00004821 ((Mnemonic == "add" &&static_cast<ARMOperand*>(Operands[5])->isReg()) ||
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004822 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004823 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004824 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4825 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004826 // selecting via the generic "add" mnemonic, so to know that we
4827 // should remove the cc_out operand, we have to explicitly check that
4828 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004829 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4830 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004831 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4832 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4833 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4834 // Nest conditions rather than one big 'if' statement for readability.
4835 //
4836 // If either register is a high reg, it's either one of the SP
4837 // variants (handled above) or a 32-bit encoding, so we just
Jim Grosbach12a88632012-01-21 00:07:56 +00004838 // check against T3. If the second register is the PC, this is an
4839 // alternate form of ADR, which uses encoding T4, so check for that too.
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004840 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4841 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
Jim Grosbach12a88632012-01-21 00:07:56 +00004842 static_cast<ARMOperand*>(Operands[4])->getReg() != ARM::PC &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004843 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4844 return false;
4845 // If both registers are low, we're in an IT block, and the immediate is
4846 // in range, we should use encoding T1 instead, which has a cc_out.
4847 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004848 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004849 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4850 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4851 return false;
4852
4853 // Otherwise, we use encoding T4, which does not have a cc_out
4854 // operand.
4855 return true;
4856 }
4857
Jim Grosbach64944f42011-09-14 21:00:40 +00004858 // The thumb2 multiply instruction doesn't have a CCOut register, so
4859 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4860 // use the 16-bit encoding or not.
4861 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4862 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4863 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4864 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4865 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4866 // If the registers aren't low regs, the destination reg isn't the
4867 // same as one of the source regs, or the cc_out operand is zero
4868 // outside of an IT block, we have to use the 32-bit encoding, so
4869 // remove the cc_out operand.
4870 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4871 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach1de0bd12011-11-15 19:29:45 +00004872 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach64944f42011-09-14 21:00:40 +00004873 !inITBlock() ||
4874 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4875 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4876 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4877 static_cast<ARMOperand*>(Operands[4])->getReg())))
4878 return true;
4879
Jim Grosbach7f1ec952011-11-15 19:55:16 +00004880 // Also check the 'mul' syntax variant that doesn't specify an explicit
4881 // destination register.
4882 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4883 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4884 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4885 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4886 // If the registers aren't low regs or the cc_out operand is zero
4887 // outside of an IT block, we have to use the 32-bit encoding, so
4888 // remove the cc_out operand.
4889 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4890 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4891 !inITBlock()))
4892 return true;
4893
Jim Grosbach64944f42011-09-14 21:00:40 +00004894
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004895
Jim Grosbachf69c8042011-08-24 21:42:27 +00004896 // Register-register 'add/sub' for thumb does not have a cc_out operand
4897 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4898 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4899 // right, this will result in better diagnostics (which operand is off)
4900 // anyway.
4901 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4902 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004903 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4904 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
Jim Grosbacha23ecc22012-04-10 17:31:55 +00004905 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4906 (static_cast<ARMOperand*>(Operands[4])->isImm() ||
4907 (Operands.size() == 6 &&
4908 static_cast<ARMOperand*>(Operands[5])->isImm())))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004909 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004910
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004911 return false;
4912}
4913
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004914static bool isDataTypeToken(StringRef Tok) {
4915 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4916 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4917 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4918 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4919 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4920 Tok == ".f" || Tok == ".d";
4921}
4922
4923// FIXME: This bit should probably be handled via an explicit match class
4924// in the .td files that matches the suffix instead of having it be
4925// a literal string token the way it is now.
4926static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4927 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4928}
4929
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004930static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004931/// Parse an arm instruction mnemonic followed by its operands.
4932bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4933 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004934 // Apply mnemonic aliases before doing anything else, as the destination
4935 // mnemnonic may include suffices and we want to handle them normally.
4936 // The generic tblgen'erated code does this later, at the start of
4937 // MatchInstructionImpl(), but that's too late for aliases that include
4938 // any sort of suffix.
4939 unsigned AvailableFeatures = getAvailableFeatures();
4940 applyMnemonicAliases(Name, AvailableFeatures);
4941
Jim Grosbacha39cda72011-12-14 02:16:11 +00004942 // First check for the ARM-specific .req directive.
4943 if (Parser.getTok().is(AsmToken::Identifier) &&
4944 Parser.getTok().getIdentifier() == ".req") {
4945 parseDirectiveReq(Name, NameLoc);
4946 // We always return 'error' for this, as we're done with this
4947 // statement and don't need to match the 'instruction."
4948 return true;
4949 }
4950
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004951 // Create the leading tokens for the mnemonic, split by '.' characters.
4952 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004953 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004954
Daniel Dunbar352e1482011-01-11 15:59:50 +00004955 // Split out the predication code and carry setting flag from the mnemonic.
4956 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004957 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004958 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004959 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004960 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004961 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004962
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004963 // In Thumb1, only the branch (B) instruction can be predicated.
4964 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4965 Parser.EatToEndOfStatement();
4966 return Error(NameLoc, "conditional execution not supported in Thumb1");
4967 }
4968
Jim Grosbachffa32252011-07-19 19:13:28 +00004969 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4970
Jim Grosbach89df9962011-08-26 21:43:41 +00004971 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4972 // is the mask as it will be for the IT encoding if the conditional
4973 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4974 // where the conditional bit0 is zero, the instruction post-processing
4975 // will adjust the mask accordingly.
4976 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004977 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4978 if (ITMask.size() > 3) {
4979 Parser.EatToEndOfStatement();
4980 return Error(Loc, "too many conditions on IT instruction");
4981 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004982 unsigned Mask = 8;
4983 for (unsigned i = ITMask.size(); i != 0; --i) {
4984 char pos = ITMask[i - 1];
4985 if (pos != 't' && pos != 'e') {
4986 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004987 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004988 }
4989 Mask >>= 1;
4990 if (ITMask[i - 1] == 't')
4991 Mask |= 8;
4992 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004993 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004994 }
4995
Jim Grosbachffa32252011-07-19 19:13:28 +00004996 // FIXME: This is all a pretty gross hack. We should automatically handle
4997 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004998
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004999 // Next, add the CCOut and ConditionCode operands, if needed.
5000 //
5001 // For mnemonics which can ever incorporate a carry setting bit or predication
5002 // code, our matching model involves us always generating CCOut and
5003 // ConditionCode operands to match the mnemonic "as written" and then we let
5004 // the matcher deal with finding the right instruction or generating an
5005 // appropriate error.
5006 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00005007 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00005008
Jim Grosbach33c16a22011-07-14 22:04:21 +00005009 // If we had a carry-set on an instruction that can't do that, issue an
5010 // error.
5011 if (!CanAcceptCarrySet && CarrySetting) {
5012 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00005013 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00005014 "' can not set flags, but 's' suffix specified");
5015 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00005016 // If we had a predication code on an instruction that can't do that, issue an
5017 // error.
5018 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
5019 Parser.EatToEndOfStatement();
5020 return Error(NameLoc, "instruction '" + Mnemonic +
5021 "' is not predicable, but condition code specified");
5022 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00005023
Daniel Dunbar3771dd02011-01-11 15:59:53 +00005024 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005025 if (CanAcceptCarrySet) {
5026 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00005027 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005028 Loc));
5029 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00005030
5031 // Add the predication code operand, if necessary.
5032 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005033 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
5034 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00005035 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005036 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00005037 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00005038
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00005039 // Add the processor imod operand, if necessary.
5040 if (ProcessorIMod) {
5041 Operands.push_back(ARMOperand::CreateImm(
5042 MCConstantExpr::Create(ProcessorIMod, getContext()),
5043 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00005044 }
5045
Daniel Dunbar345a9a62010-08-11 06:37:20 +00005046 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00005047 while (Next != StringRef::npos) {
5048 Start = Next;
5049 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00005050 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00005051
Jim Grosbach7aef99b2011-11-11 23:08:10 +00005052 // Some NEON instructions have an optional datatype suffix that is
5053 // completely ignored. Check for that.
5054 if (isDataTypeToken(ExtraToken) &&
5055 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
5056 continue;
5057
Jim Grosbach81d2e392011-09-07 16:06:04 +00005058 if (ExtraToken != ".n") {
5059 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
5060 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
5061 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00005062 }
5063
5064 // Read the remaining operands.
5065 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00005066 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00005067 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00005068 Parser.EatToEndOfStatement();
5069 return true;
5070 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00005071
5072 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00005073 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00005074
5075 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00005076 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00005077 Parser.EatToEndOfStatement();
5078 return true;
5079 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00005080 }
5081 }
Jim Grosbach16c74252010-10-29 14:46:02 +00005082
Chris Lattnercbf8a982010-09-11 16:18:25 +00005083 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00005084 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00005085 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00005086 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00005087 }
Bill Wendling146018f2010-11-06 21:42:12 +00005088
Chris Lattner34e53142010-09-08 05:10:46 +00005089 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00005090
Jim Grosbachd54b4e62011-08-16 21:12:37 +00005091 // Some instructions, mostly Thumb, have forms for the same mnemonic that
5092 // do and don't have a cc_out optional-def operand. With some spot-checks
5093 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00005094 // parse and adjust accordingly before actually matching. We shouldn't ever
5095 // try to remove a cc_out operand that was explicitly set on the the
5096 // mnemonic, of course (CarrySetting == true). Reason number #317 the
5097 // table driven matcher doesn't fit well with the ARM instruction set.
5098 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00005099 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
5100 Operands.erase(Operands.begin() + 1);
5101 delete Op;
5102 }
5103
Jim Grosbachcf121c32011-07-28 21:57:55 +00005104 // ARM mode 'blx' need special handling, as the register operand version
5105 // is predicable, but the label operand version is not. So, we can't rely
5106 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00005107 // a k_CondCode operand in the list. If we're trying to match the label
5108 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00005109 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
5110 static_cast<ARMOperand*>(Operands[2])->isImm()) {
5111 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
5112 Operands.erase(Operands.begin() + 1);
5113 delete Op;
5114 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00005115
5116 // The vector-compare-to-zero instructions have a literal token "#0" at
5117 // the end that comes to here as an immediate operand. Convert it to a
5118 // token to play nicely with the matcher.
5119 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
5120 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
5121 static_cast<ARMOperand*>(Operands[5])->isImm()) {
5122 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
5123 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
5124 if (CE && CE->getValue() == 0) {
5125 Operands.erase(Operands.begin() + 5);
5126 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5127 delete Op;
5128 }
5129 }
Jim Grosbach68259142011-10-03 22:30:24 +00005130 // VCMP{E} does the same thing, but with a different operand count.
5131 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
5132 static_cast<ARMOperand*>(Operands[4])->isImm()) {
5133 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
5134 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
5135 if (CE && CE->getValue() == 0) {
5136 Operands.erase(Operands.begin() + 4);
5137 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5138 delete Op;
5139 }
5140 }
Jim Grosbach934755a2011-08-22 23:47:13 +00005141 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
Jim Grosbach55b02f22011-12-13 20:50:38 +00005142 // end. Convert it to a token here. Take care not to convert those
5143 // that should hit the Thumb2 encoding.
Jim Grosbach934755a2011-08-22 23:47:13 +00005144 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
Jim Grosbach55b02f22011-12-13 20:50:38 +00005145 static_cast<ARMOperand*>(Operands[3])->isReg() &&
5146 static_cast<ARMOperand*>(Operands[4])->isReg() &&
Jim Grosbach934755a2011-08-22 23:47:13 +00005147 static_cast<ARMOperand*>(Operands[5])->isImm()) {
5148 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
5149 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
Jim Grosbach55b02f22011-12-13 20:50:38 +00005150 if (CE && CE->getValue() == 0 &&
5151 (isThumbOne() ||
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00005152 // The cc_out operand matches the IT block.
5153 ((inITBlock() != CarrySetting) &&
5154 // Neither register operand is a high register.
Jim Grosbach55b02f22011-12-13 20:50:38 +00005155 (isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00005156 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()))))){
Jim Grosbach934755a2011-08-22 23:47:13 +00005157 Operands.erase(Operands.begin() + 5);
5158 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5159 delete Op;
5160 }
5161 }
5162
Chris Lattner98986712010-01-14 22:21:20 +00005163 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005164}
5165
Jim Grosbach189610f2011-07-26 18:25:39 +00005166// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00005167
5168// return 'true' if register list contains non-low GPR registers,
5169// 'false' otherwise. If Reg is in the register list or is HiReg, set
5170// 'containsReg' to true.
5171static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
5172 unsigned HiReg, bool &containsReg) {
5173 containsReg = false;
5174 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5175 unsigned OpReg = Inst.getOperand(i).getReg();
5176 if (OpReg == Reg)
5177 containsReg = true;
5178 // Anything other than a low register isn't legal here.
5179 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
5180 return true;
5181 }
5182 return false;
5183}
5184
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005185// Check if the specified regisgter is in the register list of the inst,
5186// starting at the indicated operand number.
5187static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
5188 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5189 unsigned OpReg = Inst.getOperand(i).getReg();
5190 if (OpReg == Reg)
5191 return true;
5192 }
5193 return false;
5194}
5195
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005196// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
5197// the ARMInsts array) instead. Getting that here requires awkward
5198// API changes, though. Better way?
5199namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005200extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005201}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005202static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005203 return ARMInsts[Opcode];
5204}
5205
Jim Grosbach189610f2011-07-26 18:25:39 +00005206// FIXME: We would really like to be able to tablegen'erate this.
5207bool ARMAsmParser::
5208validateInstruction(MCInst &Inst,
5209 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005210 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005211 SMLoc Loc = Operands[0]->getStartLoc();
5212 // Check the IT block state first.
Jim Grosbach74423e32012-01-25 19:52:01 +00005213 // NOTE: BKPT instruction has the interesting property of being
5214 // allowed in IT blocks, but not being predicable. It just always
Owen Andersonb6b7f512011-09-13 17:59:19 +00005215 // executes.
Jim Grosbach74423e32012-01-25 19:52:01 +00005216 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT &&
5217 Inst.getOpcode() != ARM::BKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005218 unsigned bit = 1;
5219 if (ITState.FirstCond)
5220 ITState.FirstCond = false;
5221 else
Jim Grosbacha1109882011-09-02 23:22:08 +00005222 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005223 // The instruction must be predicable.
5224 if (!MCID.isPredicable())
5225 return Error(Loc, "instructions in IT block must be predicable");
5226 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
5227 unsigned ITCond = bit ? ITState.Cond :
5228 ARMCC::getOppositeCondition(ITState.Cond);
5229 if (Cond != ITCond) {
5230 // Find the condition code Operand to get its SMLoc information.
5231 SMLoc CondLoc;
5232 for (unsigned i = 1; i < Operands.size(); ++i)
5233 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
5234 CondLoc = Operands[i]->getStartLoc();
5235 return Error(CondLoc, "incorrect condition in IT block; got '" +
5236 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
5237 "', but expected '" +
5238 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
5239 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00005240 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005241 } else if (isThumbTwo() && MCID.isPredicable() &&
5242 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005243 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
5244 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005245 return Error(Loc, "predicated instructions must be in IT block");
5246
Jim Grosbach189610f2011-07-26 18:25:39 +00005247 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00005248 case ARM::LDRD:
5249 case ARM::LDRD_PRE:
5250 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005251 case ARM::LDREXD: {
5252 // Rt2 must be Rt + 1.
5253 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5254 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5255 if (Rt2 != Rt + 1)
5256 return Error(Operands[3]->getStartLoc(),
5257 "destination operands must be sequential");
5258 return false;
5259 }
Jim Grosbach14605d12011-08-11 20:28:23 +00005260 case ARM::STRD: {
5261 // Rt2 must be Rt + 1.
5262 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5263 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5264 if (Rt2 != Rt + 1)
5265 return Error(Operands[3]->getStartLoc(),
5266 "source operands must be sequential");
5267 return false;
5268 }
Jim Grosbach53642c52011-08-10 20:49:18 +00005269 case ARM::STRD_PRE:
5270 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005271 case ARM::STREXD: {
5272 // Rt2 must be Rt + 1.
5273 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5274 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
5275 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00005276 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00005277 "source operands must be sequential");
5278 return false;
5279 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005280 case ARM::SBFX:
5281 case ARM::UBFX: {
5282 // width must be in range [1, 32-lsb]
5283 unsigned lsb = Inst.getOperand(2).getImm();
5284 unsigned widthm1 = Inst.getOperand(3).getImm();
5285 if (widthm1 >= 32 - lsb)
5286 return Error(Operands[5]->getStartLoc(),
5287 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00005288 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005289 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005290 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005291 // If we're parsing Thumb2, the .w variant is available and handles
5292 // most cases that are normally illegal for a Thumb1 LDM
5293 // instruction. We'll make the transformation in processInstruction()
5294 // if necessary.
5295 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005296 // Thumb LDM instructions are writeback iff the base register is not
5297 // in the register list.
5298 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005299 bool hasWritebackToken =
5300 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5301 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00005302 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005303 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005304 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
5305 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005306 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005307 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005308 return Error(Operands[2]->getStartLoc(),
5309 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005310 // If we should not have writeback, there must not be a '!'. This is
5311 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00005312 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005313 return Error(Operands[3]->getStartLoc(),
5314 "writeback operator '!' not allowed when base register "
5315 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005316
5317 break;
5318 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005319 case ARM::t2LDMIA_UPD: {
5320 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
5321 return Error(Operands[4]->getStartLoc(),
5322 "writeback operator '!' not allowed when base register "
5323 "in register list");
5324 break;
5325 }
Jim Grosbach54026372011-11-10 23:17:11 +00005326 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
5327 // so only issue a diagnostic for thumb1. The instructions will be
5328 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005329 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005330 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005331 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
5332 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005333 return Error(Operands[2]->getStartLoc(),
5334 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005335 break;
5336 }
5337 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005338 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005339 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
5340 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005341 return Error(Operands[2]->getStartLoc(),
5342 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005343 break;
5344 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00005345 case ARM::tSTMIA_UPD: {
5346 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00005347 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00005348 return Error(Operands[4]->getStartLoc(),
5349 "registers must be in range r0-r7");
5350 break;
5351 }
Jim Grosbacha9cc08f2012-04-27 23:51:36 +00005352 case ARM::tADDrSP: {
5353 // If the non-SP source operand and the destination operand are not the
5354 // same, we need thumb2 (for the wide encoding), or we have an error.
5355 if (!isThumbTwo() &&
5356 Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg()) {
5357 return Error(Operands[4]->getStartLoc(),
5358 "source register must be the same as destination");
5359 }
5360 break;
5361 }
Jim Grosbach189610f2011-07-26 18:25:39 +00005362 }
5363
5364 return false;
5365}
5366
Jim Grosbachd7433e22012-01-23 23:45:44 +00005367static unsigned getRealVSTOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach84defb52011-12-02 22:34:51 +00005368 switch(Opc) {
Craig Topperbc219812012-02-07 02:50:20 +00005369 default: llvm_unreachable("unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005370 // VST1LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005371 case ARM::VST1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
5372 case ARM::VST1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
5373 case ARM::VST1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
5374 case ARM::VST1LNdWB_register_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
5375 case ARM::VST1LNdWB_register_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
5376 case ARM::VST1LNdWB_register_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
5377 case ARM::VST1LNdAsm_8: Spacing = 1; return ARM::VST1LNd8;
5378 case ARM::VST1LNdAsm_16: Spacing = 1; return ARM::VST1LNd16;
5379 case ARM::VST1LNdAsm_32: Spacing = 1; return ARM::VST1LNd32;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005380
5381 // VST2LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005382 case ARM::VST2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
5383 case ARM::VST2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
5384 case ARM::VST2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
5385 case ARM::VST2LNqWB_fixed_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
5386 case ARM::VST2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005387
Jim Grosbach7945ead2012-01-24 00:43:12 +00005388 case ARM::VST2LNdWB_register_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
5389 case ARM::VST2LNdWB_register_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
5390 case ARM::VST2LNdWB_register_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
5391 case ARM::VST2LNqWB_register_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
5392 case ARM::VST2LNqWB_register_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005393
Jim Grosbach7945ead2012-01-24 00:43:12 +00005394 case ARM::VST2LNdAsm_8: Spacing = 1; return ARM::VST2LNd8;
5395 case ARM::VST2LNdAsm_16: Spacing = 1; return ARM::VST2LNd16;
5396 case ARM::VST2LNdAsm_32: Spacing = 1; return ARM::VST2LNd32;
5397 case ARM::VST2LNqAsm_16: Spacing = 2; return ARM::VST2LNq16;
5398 case ARM::VST2LNqAsm_32: Spacing = 2; return ARM::VST2LNq32;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005399
Jim Grosbach4adb1822012-01-24 00:07:41 +00005400 // VST3LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005401 case ARM::VST3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
5402 case ARM::VST3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
5403 case ARM::VST3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
5404 case ARM::VST3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNq16_UPD;
5405 case ARM::VST3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
5406 case ARM::VST3LNdWB_register_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
5407 case ARM::VST3LNdWB_register_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
5408 case ARM::VST3LNdWB_register_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
5409 case ARM::VST3LNqWB_register_Asm_16: Spacing = 2; return ARM::VST3LNq16_UPD;
5410 case ARM::VST3LNqWB_register_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
5411 case ARM::VST3LNdAsm_8: Spacing = 1; return ARM::VST3LNd8;
5412 case ARM::VST3LNdAsm_16: Spacing = 1; return ARM::VST3LNd16;
5413 case ARM::VST3LNdAsm_32: Spacing = 1; return ARM::VST3LNd32;
5414 case ARM::VST3LNqAsm_16: Spacing = 2; return ARM::VST3LNq16;
5415 case ARM::VST3LNqAsm_32: Spacing = 2; return ARM::VST3LNq32;
Jim Grosbach4adb1822012-01-24 00:07:41 +00005416
Jim Grosbachd7433e22012-01-23 23:45:44 +00005417 // VST3
Jim Grosbach7945ead2012-01-24 00:43:12 +00005418 case ARM::VST3dWB_fixed_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
5419 case ARM::VST3dWB_fixed_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
5420 case ARM::VST3dWB_fixed_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
5421 case ARM::VST3qWB_fixed_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
5422 case ARM::VST3qWB_fixed_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
5423 case ARM::VST3qWB_fixed_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
5424 case ARM::VST3dWB_register_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
5425 case ARM::VST3dWB_register_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
5426 case ARM::VST3dWB_register_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
5427 case ARM::VST3qWB_register_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
5428 case ARM::VST3qWB_register_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
5429 case ARM::VST3qWB_register_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
5430 case ARM::VST3dAsm_8: Spacing = 1; return ARM::VST3d8;
5431 case ARM::VST3dAsm_16: Spacing = 1; return ARM::VST3d16;
5432 case ARM::VST3dAsm_32: Spacing = 1; return ARM::VST3d32;
5433 case ARM::VST3qAsm_8: Spacing = 2; return ARM::VST3q8;
5434 case ARM::VST3qAsm_16: Spacing = 2; return ARM::VST3q16;
5435 case ARM::VST3qAsm_32: Spacing = 2; return ARM::VST3q32;
Jim Grosbach539aab72012-01-24 00:58:13 +00005436
Jim Grosbach88a54de2012-01-24 18:53:13 +00005437 // VST4LN
5438 case ARM::VST4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD;
5439 case ARM::VST4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD;
5440 case ARM::VST4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD;
5441 case ARM::VST4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNq16_UPD;
5442 case ARM::VST4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD;
5443 case ARM::VST4LNdWB_register_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD;
5444 case ARM::VST4LNdWB_register_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD;
5445 case ARM::VST4LNdWB_register_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD;
5446 case ARM::VST4LNqWB_register_Asm_16: Spacing = 2; return ARM::VST4LNq16_UPD;
5447 case ARM::VST4LNqWB_register_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD;
5448 case ARM::VST4LNdAsm_8: Spacing = 1; return ARM::VST4LNd8;
5449 case ARM::VST4LNdAsm_16: Spacing = 1; return ARM::VST4LNd16;
5450 case ARM::VST4LNdAsm_32: Spacing = 1; return ARM::VST4LNd32;
5451 case ARM::VST4LNqAsm_16: Spacing = 2; return ARM::VST4LNq16;
5452 case ARM::VST4LNqAsm_32: Spacing = 2; return ARM::VST4LNq32;
5453
Jim Grosbach539aab72012-01-24 00:58:13 +00005454 // VST4
5455 case ARM::VST4dWB_fixed_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
5456 case ARM::VST4dWB_fixed_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
5457 case ARM::VST4dWB_fixed_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
5458 case ARM::VST4qWB_fixed_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
5459 case ARM::VST4qWB_fixed_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
5460 case ARM::VST4qWB_fixed_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
5461 case ARM::VST4dWB_register_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
5462 case ARM::VST4dWB_register_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
5463 case ARM::VST4dWB_register_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
5464 case ARM::VST4qWB_register_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
5465 case ARM::VST4qWB_register_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
5466 case ARM::VST4qWB_register_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
5467 case ARM::VST4dAsm_8: Spacing = 1; return ARM::VST4d8;
5468 case ARM::VST4dAsm_16: Spacing = 1; return ARM::VST4d16;
5469 case ARM::VST4dAsm_32: Spacing = 1; return ARM::VST4d32;
5470 case ARM::VST4qAsm_8: Spacing = 2; return ARM::VST4q8;
5471 case ARM::VST4qAsm_16: Spacing = 2; return ARM::VST4q16;
5472 case ARM::VST4qAsm_32: Spacing = 2; return ARM::VST4q32;
Jim Grosbach84defb52011-12-02 22:34:51 +00005473 }
5474}
5475
Jim Grosbachd7433e22012-01-23 23:45:44 +00005476static unsigned getRealVLDOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005477 switch(Opc) {
Craig Topperbc219812012-02-07 02:50:20 +00005478 default: llvm_unreachable("unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005479 // VLD1LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005480 case ARM::VLD1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
5481 case ARM::VLD1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
5482 case ARM::VLD1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
5483 case ARM::VLD1LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
5484 case ARM::VLD1LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
5485 case ARM::VLD1LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
5486 case ARM::VLD1LNdAsm_8: Spacing = 1; return ARM::VLD1LNd8;
5487 case ARM::VLD1LNdAsm_16: Spacing = 1; return ARM::VLD1LNd16;
5488 case ARM::VLD1LNdAsm_32: Spacing = 1; return ARM::VLD1LNd32;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005489
5490 // VLD2LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005491 case ARM::VLD2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
5492 case ARM::VLD2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
5493 case ARM::VLD2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
5494 case ARM::VLD2LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNq16_UPD;
5495 case ARM::VLD2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
5496 case ARM::VLD2LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
5497 case ARM::VLD2LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
5498 case ARM::VLD2LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
5499 case ARM::VLD2LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD2LNq16_UPD;
5500 case ARM::VLD2LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
5501 case ARM::VLD2LNdAsm_8: Spacing = 1; return ARM::VLD2LNd8;
5502 case ARM::VLD2LNdAsm_16: Spacing = 1; return ARM::VLD2LNd16;
5503 case ARM::VLD2LNdAsm_32: Spacing = 1; return ARM::VLD2LNd32;
5504 case ARM::VLD2LNqAsm_16: Spacing = 2; return ARM::VLD2LNq16;
5505 case ARM::VLD2LNqAsm_32: Spacing = 2; return ARM::VLD2LNq32;
Jim Grosbach3a678af2012-01-23 21:53:26 +00005506
Jim Grosbach5e59f7e2012-01-24 23:47:04 +00005507 // VLD3DUP
5508 case ARM::VLD3DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD;
5509 case ARM::VLD3DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD;
5510 case ARM::VLD3DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD;
5511 case ARM::VLD3DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPq8_UPD;
5512 case ARM::VLD3DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPq16_UPD;
5513 case ARM::VLD3DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD;
5514 case ARM::VLD3DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD;
5515 case ARM::VLD3DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD;
5516 case ARM::VLD3DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD;
5517 case ARM::VLD3DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD3DUPq8_UPD;
5518 case ARM::VLD3DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD3DUPq16_UPD;
5519 case ARM::VLD3DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD;
5520 case ARM::VLD3DUPdAsm_8: Spacing = 1; return ARM::VLD3DUPd8;
5521 case ARM::VLD3DUPdAsm_16: Spacing = 1; return ARM::VLD3DUPd16;
5522 case ARM::VLD3DUPdAsm_32: Spacing = 1; return ARM::VLD3DUPd32;
5523 case ARM::VLD3DUPqAsm_8: Spacing = 2; return ARM::VLD3DUPq8;
5524 case ARM::VLD3DUPqAsm_16: Spacing = 2; return ARM::VLD3DUPq16;
5525 case ARM::VLD3DUPqAsm_32: Spacing = 2; return ARM::VLD3DUPq32;
5526
Jim Grosbach3a678af2012-01-23 21:53:26 +00005527 // VLD3LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005528 case ARM::VLD3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
5529 case ARM::VLD3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
5530 case ARM::VLD3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
5531 case ARM::VLD3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNq16_UPD;
5532 case ARM::VLD3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
5533 case ARM::VLD3LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
5534 case ARM::VLD3LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
5535 case ARM::VLD3LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
5536 case ARM::VLD3LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD3LNq16_UPD;
5537 case ARM::VLD3LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
5538 case ARM::VLD3LNdAsm_8: Spacing = 1; return ARM::VLD3LNd8;
5539 case ARM::VLD3LNdAsm_16: Spacing = 1; return ARM::VLD3LNd16;
5540 case ARM::VLD3LNdAsm_32: Spacing = 1; return ARM::VLD3LNd32;
5541 case ARM::VLD3LNqAsm_16: Spacing = 2; return ARM::VLD3LNq16;
5542 case ARM::VLD3LNqAsm_32: Spacing = 2; return ARM::VLD3LNq32;
Jim Grosbachc387fc62012-01-23 23:20:46 +00005543
5544 // VLD3
Jim Grosbach7945ead2012-01-24 00:43:12 +00005545 case ARM::VLD3dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
5546 case ARM::VLD3dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
5547 case ARM::VLD3dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
5548 case ARM::VLD3qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
5549 case ARM::VLD3qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
5550 case ARM::VLD3qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
5551 case ARM::VLD3dWB_register_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
5552 case ARM::VLD3dWB_register_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
5553 case ARM::VLD3dWB_register_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
5554 case ARM::VLD3qWB_register_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
5555 case ARM::VLD3qWB_register_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
5556 case ARM::VLD3qWB_register_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
5557 case ARM::VLD3dAsm_8: Spacing = 1; return ARM::VLD3d8;
5558 case ARM::VLD3dAsm_16: Spacing = 1; return ARM::VLD3d16;
5559 case ARM::VLD3dAsm_32: Spacing = 1; return ARM::VLD3d32;
5560 case ARM::VLD3qAsm_8: Spacing = 2; return ARM::VLD3q8;
5561 case ARM::VLD3qAsm_16: Spacing = 2; return ARM::VLD3q16;
5562 case ARM::VLD3qAsm_32: Spacing = 2; return ARM::VLD3q32;
Jim Grosbach8abe7e32012-01-24 00:43:17 +00005563
Jim Grosbache983a132012-01-24 18:37:25 +00005564 // VLD4LN
5565 case ARM::VLD4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD;
5566 case ARM::VLD4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
5567 case ARM::VLD4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
5568 case ARM::VLD4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNq16_UPD;
5569 case ARM::VLD4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
5570 case ARM::VLD4LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD;
5571 case ARM::VLD4LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
5572 case ARM::VLD4LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
5573 case ARM::VLD4LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD4LNq16_UPD;
5574 case ARM::VLD4LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
5575 case ARM::VLD4LNdAsm_8: Spacing = 1; return ARM::VLD4LNd8;
5576 case ARM::VLD4LNdAsm_16: Spacing = 1; return ARM::VLD4LNd16;
5577 case ARM::VLD4LNdAsm_32: Spacing = 1; return ARM::VLD4LNd32;
5578 case ARM::VLD4LNqAsm_16: Spacing = 2; return ARM::VLD4LNq16;
5579 case ARM::VLD4LNqAsm_32: Spacing = 2; return ARM::VLD4LNq32;
5580
Jim Grosbacha57a36a2012-01-25 00:01:08 +00005581 // VLD4DUP
5582 case ARM::VLD4DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD;
5583 case ARM::VLD4DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD;
5584 case ARM::VLD4DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD;
5585 case ARM::VLD4DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPq8_UPD;
5586 case ARM::VLD4DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPq16_UPD;
5587 case ARM::VLD4DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD;
5588 case ARM::VLD4DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD;
5589 case ARM::VLD4DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD;
5590 case ARM::VLD4DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD;
5591 case ARM::VLD4DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD4DUPq8_UPD;
5592 case ARM::VLD4DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD4DUPq16_UPD;
5593 case ARM::VLD4DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD;
5594 case ARM::VLD4DUPdAsm_8: Spacing = 1; return ARM::VLD4DUPd8;
5595 case ARM::VLD4DUPdAsm_16: Spacing = 1; return ARM::VLD4DUPd16;
5596 case ARM::VLD4DUPdAsm_32: Spacing = 1; return ARM::VLD4DUPd32;
5597 case ARM::VLD4DUPqAsm_8: Spacing = 2; return ARM::VLD4DUPq8;
5598 case ARM::VLD4DUPqAsm_16: Spacing = 2; return ARM::VLD4DUPq16;
5599 case ARM::VLD4DUPqAsm_32: Spacing = 2; return ARM::VLD4DUPq32;
5600
Jim Grosbach8abe7e32012-01-24 00:43:17 +00005601 // VLD4
5602 case ARM::VLD4dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
5603 case ARM::VLD4dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
5604 case ARM::VLD4dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
5605 case ARM::VLD4qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
5606 case ARM::VLD4qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
5607 case ARM::VLD4qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
5608 case ARM::VLD4dWB_register_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
5609 case ARM::VLD4dWB_register_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
5610 case ARM::VLD4dWB_register_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
5611 case ARM::VLD4qWB_register_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
5612 case ARM::VLD4qWB_register_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
5613 case ARM::VLD4qWB_register_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
5614 case ARM::VLD4dAsm_8: Spacing = 1; return ARM::VLD4d8;
5615 case ARM::VLD4dAsm_16: Spacing = 1; return ARM::VLD4d16;
5616 case ARM::VLD4dAsm_32: Spacing = 1; return ARM::VLD4d32;
5617 case ARM::VLD4qAsm_8: Spacing = 2; return ARM::VLD4q8;
5618 case ARM::VLD4qAsm_16: Spacing = 2; return ARM::VLD4q16;
5619 case ARM::VLD4qAsm_32: Spacing = 2; return ARM::VLD4q32;
Jim Grosbach7636bf62011-12-02 00:35:16 +00005620 }
5621}
5622
Jim Grosbach83ec8772011-11-10 23:42:14 +00005623bool ARMAsmParser::
Jim Grosbachf8fce712011-08-11 17:35:48 +00005624processInstruction(MCInst &Inst,
5625 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5626 switch (Inst.getOpcode()) {
Jim Grosbach0b4c6732012-01-18 22:46:46 +00005627 // Aliases for alternate PC+imm syntax of LDR instructions.
5628 case ARM::t2LDRpcrel:
5629 Inst.setOpcode(ARM::t2LDRpci);
5630 return true;
5631 case ARM::t2LDRBpcrel:
5632 Inst.setOpcode(ARM::t2LDRBpci);
5633 return true;
5634 case ARM::t2LDRHpcrel:
5635 Inst.setOpcode(ARM::t2LDRHpci);
5636 return true;
5637 case ARM::t2LDRSBpcrel:
5638 Inst.setOpcode(ARM::t2LDRSBpci);
5639 return true;
5640 case ARM::t2LDRSHpcrel:
5641 Inst.setOpcode(ARM::t2LDRSHpci);
5642 return true;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005643 // Handle NEON VST complex aliases.
Jim Grosbach8b31f952012-01-23 19:39:08 +00005644 case ARM::VST1LNdWB_register_Asm_8:
5645 case ARM::VST1LNdWB_register_Asm_16:
5646 case ARM::VST1LNdWB_register_Asm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005647 MCInst TmpInst;
5648 // Shuffle the operands around so the lane index operand is in the
5649 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005650 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005651 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005652 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5653 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5654 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5655 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5656 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5657 TmpInst.addOperand(Inst.getOperand(1)); // lane
5658 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5659 TmpInst.addOperand(Inst.getOperand(6));
5660 Inst = TmpInst;
5661 return true;
5662 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005663
Jim Grosbach8b31f952012-01-23 19:39:08 +00005664 case ARM::VST2LNdWB_register_Asm_8:
5665 case ARM::VST2LNdWB_register_Asm_16:
5666 case ARM::VST2LNdWB_register_Asm_32:
5667 case ARM::VST2LNqWB_register_Asm_16:
5668 case ARM::VST2LNqWB_register_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005669 MCInst TmpInst;
5670 // Shuffle the operands around so the lane index operand is in the
5671 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005672 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005673 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005674 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5675 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5676 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5677 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5678 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005679 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5680 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005681 TmpInst.addOperand(Inst.getOperand(1)); // lane
5682 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5683 TmpInst.addOperand(Inst.getOperand(6));
5684 Inst = TmpInst;
5685 return true;
5686 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005687
5688 case ARM::VST3LNdWB_register_Asm_8:
5689 case ARM::VST3LNdWB_register_Asm_16:
5690 case ARM::VST3LNdWB_register_Asm_32:
5691 case ARM::VST3LNqWB_register_Asm_16:
5692 case ARM::VST3LNqWB_register_Asm_32: {
5693 MCInst TmpInst;
5694 // Shuffle the operands around so the lane index operand is in the
5695 // right place.
5696 unsigned Spacing;
5697 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5698 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5699 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5700 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5701 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5702 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5703 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5704 Spacing));
5705 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5706 Spacing * 2));
5707 TmpInst.addOperand(Inst.getOperand(1)); // lane
5708 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5709 TmpInst.addOperand(Inst.getOperand(6));
5710 Inst = TmpInst;
5711 return true;
5712 }
5713
Jim Grosbach88a54de2012-01-24 18:53:13 +00005714 case ARM::VST4LNdWB_register_Asm_8:
5715 case ARM::VST4LNdWB_register_Asm_16:
5716 case ARM::VST4LNdWB_register_Asm_32:
5717 case ARM::VST4LNqWB_register_Asm_16:
5718 case ARM::VST4LNqWB_register_Asm_32: {
5719 MCInst TmpInst;
5720 // Shuffle the operands around so the lane index operand is in the
5721 // right place.
5722 unsigned Spacing;
5723 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5724 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5725 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5726 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5727 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5728 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5729 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5730 Spacing));
5731 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5732 Spacing * 2));
5733 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5734 Spacing * 3));
5735 TmpInst.addOperand(Inst.getOperand(1)); // lane
5736 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5737 TmpInst.addOperand(Inst.getOperand(6));
5738 Inst = TmpInst;
5739 return true;
5740 }
5741
Jim Grosbach8b31f952012-01-23 19:39:08 +00005742 case ARM::VST1LNdWB_fixed_Asm_8:
5743 case ARM::VST1LNdWB_fixed_Asm_16:
5744 case ARM::VST1LNdWB_fixed_Asm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005745 MCInst TmpInst;
5746 // Shuffle the operands around so the lane index operand is in the
5747 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005748 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005749 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005750 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5751 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5752 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5753 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5754 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5755 TmpInst.addOperand(Inst.getOperand(1)); // lane
5756 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5757 TmpInst.addOperand(Inst.getOperand(5));
5758 Inst = TmpInst;
5759 return true;
5760 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005761
Jim Grosbach8b31f952012-01-23 19:39:08 +00005762 case ARM::VST2LNdWB_fixed_Asm_8:
5763 case ARM::VST2LNdWB_fixed_Asm_16:
5764 case ARM::VST2LNdWB_fixed_Asm_32:
5765 case ARM::VST2LNqWB_fixed_Asm_16:
5766 case ARM::VST2LNqWB_fixed_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005767 MCInst TmpInst;
5768 // Shuffle the operands around so the lane index operand is in the
5769 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005770 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005771 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005772 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5773 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5774 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5775 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5776 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005777 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5778 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005779 TmpInst.addOperand(Inst.getOperand(1)); // lane
5780 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5781 TmpInst.addOperand(Inst.getOperand(5));
5782 Inst = TmpInst;
5783 return true;
5784 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005785
5786 case ARM::VST3LNdWB_fixed_Asm_8:
5787 case ARM::VST3LNdWB_fixed_Asm_16:
5788 case ARM::VST3LNdWB_fixed_Asm_32:
5789 case ARM::VST3LNqWB_fixed_Asm_16:
5790 case ARM::VST3LNqWB_fixed_Asm_32: {
5791 MCInst TmpInst;
5792 // Shuffle the operands around so the lane index operand is in the
5793 // right place.
5794 unsigned Spacing;
5795 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5796 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5797 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5798 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5799 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5800 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5801 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5802 Spacing));
5803 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5804 Spacing * 2));
5805 TmpInst.addOperand(Inst.getOperand(1)); // lane
5806 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5807 TmpInst.addOperand(Inst.getOperand(5));
5808 Inst = TmpInst;
5809 return true;
5810 }
5811
Jim Grosbach88a54de2012-01-24 18:53:13 +00005812 case ARM::VST4LNdWB_fixed_Asm_8:
5813 case ARM::VST4LNdWB_fixed_Asm_16:
5814 case ARM::VST4LNdWB_fixed_Asm_32:
5815 case ARM::VST4LNqWB_fixed_Asm_16:
5816 case ARM::VST4LNqWB_fixed_Asm_32: {
5817 MCInst TmpInst;
5818 // Shuffle the operands around so the lane index operand is in the
5819 // right place.
5820 unsigned Spacing;
5821 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5822 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5823 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5824 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5825 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5826 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5827 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5828 Spacing));
5829 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5830 Spacing * 2));
5831 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5832 Spacing * 3));
5833 TmpInst.addOperand(Inst.getOperand(1)); // lane
5834 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5835 TmpInst.addOperand(Inst.getOperand(5));
5836 Inst = TmpInst;
5837 return true;
5838 }
5839
Jim Grosbach8b31f952012-01-23 19:39:08 +00005840 case ARM::VST1LNdAsm_8:
5841 case ARM::VST1LNdAsm_16:
5842 case ARM::VST1LNdAsm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005843 MCInst TmpInst;
5844 // Shuffle the operands around so the lane index operand is in the
5845 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005846 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005847 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005848 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5849 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5850 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5851 TmpInst.addOperand(Inst.getOperand(1)); // lane
5852 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5853 TmpInst.addOperand(Inst.getOperand(5));
5854 Inst = TmpInst;
5855 return true;
5856 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005857
Jim Grosbach8b31f952012-01-23 19:39:08 +00005858 case ARM::VST2LNdAsm_8:
5859 case ARM::VST2LNdAsm_16:
5860 case ARM::VST2LNdAsm_32:
5861 case ARM::VST2LNqAsm_16:
5862 case ARM::VST2LNqAsm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005863 MCInst TmpInst;
5864 // Shuffle the operands around so the lane index operand is in the
5865 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005866 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005867 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005868 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5869 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5870 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005871 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5872 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005873 TmpInst.addOperand(Inst.getOperand(1)); // lane
5874 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5875 TmpInst.addOperand(Inst.getOperand(5));
5876 Inst = TmpInst;
5877 return true;
5878 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005879
5880 case ARM::VST3LNdAsm_8:
5881 case ARM::VST3LNdAsm_16:
5882 case ARM::VST3LNdAsm_32:
5883 case ARM::VST3LNqAsm_16:
5884 case ARM::VST3LNqAsm_32: {
5885 MCInst TmpInst;
5886 // Shuffle the operands around so the lane index operand is in the
5887 // right place.
5888 unsigned Spacing;
5889 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5890 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5891 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5892 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5893 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5894 Spacing));
5895 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5896 Spacing * 2));
5897 TmpInst.addOperand(Inst.getOperand(1)); // lane
5898 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5899 TmpInst.addOperand(Inst.getOperand(5));
5900 Inst = TmpInst;
5901 return true;
5902 }
5903
Jim Grosbach88a54de2012-01-24 18:53:13 +00005904 case ARM::VST4LNdAsm_8:
5905 case ARM::VST4LNdAsm_16:
5906 case ARM::VST4LNdAsm_32:
5907 case ARM::VST4LNqAsm_16:
5908 case ARM::VST4LNqAsm_32: {
5909 MCInst TmpInst;
5910 // Shuffle the operands around so the lane index operand is in the
5911 // right place.
5912 unsigned Spacing;
5913 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5914 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5915 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5916 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5917 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5918 Spacing));
5919 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5920 Spacing * 2));
5921 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5922 Spacing * 3));
5923 TmpInst.addOperand(Inst.getOperand(1)); // lane
5924 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5925 TmpInst.addOperand(Inst.getOperand(5));
5926 Inst = TmpInst;
5927 return true;
5928 }
5929
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005930 // Handle NEON VLD complex aliases.
Jim Grosbach8b31f952012-01-23 19:39:08 +00005931 case ARM::VLD1LNdWB_register_Asm_8:
5932 case ARM::VLD1LNdWB_register_Asm_16:
5933 case ARM::VLD1LNdWB_register_Asm_32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005934 MCInst TmpInst;
5935 // Shuffle the operands around so the lane index operand is in the
5936 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005937 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005938 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005939 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5940 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5941 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5942 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5943 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5944 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5945 TmpInst.addOperand(Inst.getOperand(1)); // lane
5946 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5947 TmpInst.addOperand(Inst.getOperand(6));
5948 Inst = TmpInst;
5949 return true;
5950 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005951
Jim Grosbach8b31f952012-01-23 19:39:08 +00005952 case ARM::VLD2LNdWB_register_Asm_8:
5953 case ARM::VLD2LNdWB_register_Asm_16:
5954 case ARM::VLD2LNdWB_register_Asm_32:
5955 case ARM::VLD2LNqWB_register_Asm_16:
5956 case ARM::VLD2LNqWB_register_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005957 MCInst TmpInst;
5958 // Shuffle the operands around so the lane index operand is in the
5959 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005960 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005961 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005962 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005963 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5964 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005965 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5966 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5967 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5968 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5969 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005970 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5971 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005972 TmpInst.addOperand(Inst.getOperand(1)); // lane
5973 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5974 TmpInst.addOperand(Inst.getOperand(6));
5975 Inst = TmpInst;
5976 return true;
5977 }
5978
Jim Grosbach3a678af2012-01-23 21:53:26 +00005979 case ARM::VLD3LNdWB_register_Asm_8:
5980 case ARM::VLD3LNdWB_register_Asm_16:
5981 case ARM::VLD3LNdWB_register_Asm_32:
5982 case ARM::VLD3LNqWB_register_Asm_16:
5983 case ARM::VLD3LNqWB_register_Asm_32: {
5984 MCInst TmpInst;
5985 // Shuffle the operands around so the lane index operand is in the
5986 // right place.
5987 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005988 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005989 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5990 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5991 Spacing));
5992 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005993 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005994 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5995 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5996 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5997 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5998 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5999 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6000 Spacing));
6001 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006002 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006003 TmpInst.addOperand(Inst.getOperand(1)); // lane
6004 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
6005 TmpInst.addOperand(Inst.getOperand(6));
6006 Inst = TmpInst;
6007 return true;
6008 }
6009
Jim Grosbache983a132012-01-24 18:37:25 +00006010 case ARM::VLD4LNdWB_register_Asm_8:
6011 case ARM::VLD4LNdWB_register_Asm_16:
6012 case ARM::VLD4LNdWB_register_Asm_32:
6013 case ARM::VLD4LNqWB_register_Asm_16:
6014 case ARM::VLD4LNqWB_register_Asm_32: {
6015 MCInst TmpInst;
6016 // Shuffle the operands around so the lane index operand is in the
6017 // right place.
6018 unsigned Spacing;
6019 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6020 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6021 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6022 Spacing));
6023 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6024 Spacing * 2));
6025 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6026 Spacing * 3));
6027 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6028 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6029 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6030 TmpInst.addOperand(Inst.getOperand(4)); // Rm
6031 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6032 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6033 Spacing));
6034 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6035 Spacing * 2));
6036 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6037 Spacing * 3));
6038 TmpInst.addOperand(Inst.getOperand(1)); // lane
6039 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
6040 TmpInst.addOperand(Inst.getOperand(6));
6041 Inst = TmpInst;
6042 return true;
6043 }
6044
Jim Grosbach8b31f952012-01-23 19:39:08 +00006045 case ARM::VLD1LNdWB_fixed_Asm_8:
6046 case ARM::VLD1LNdWB_fixed_Asm_16:
6047 case ARM::VLD1LNdWB_fixed_Asm_32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00006048 MCInst TmpInst;
6049 // Shuffle the operands around so the lane index operand is in the
6050 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006051 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006052 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00006053 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6054 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6055 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6056 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6057 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6058 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6059 TmpInst.addOperand(Inst.getOperand(1)); // lane
6060 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6061 TmpInst.addOperand(Inst.getOperand(5));
6062 Inst = TmpInst;
6063 return true;
6064 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006065
Jim Grosbach8b31f952012-01-23 19:39:08 +00006066 case ARM::VLD2LNdWB_fixed_Asm_8:
6067 case ARM::VLD2LNdWB_fixed_Asm_16:
6068 case ARM::VLD2LNdWB_fixed_Asm_32:
6069 case ARM::VLD2LNqWB_fixed_Asm_16:
6070 case ARM::VLD2LNqWB_fixed_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006071 MCInst TmpInst;
6072 // Shuffle the operands around so the lane index operand is in the
6073 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006074 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006075 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006076 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006077 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6078 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006079 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6080 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6081 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6082 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6083 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006084 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6085 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006086 TmpInst.addOperand(Inst.getOperand(1)); // lane
6087 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6088 TmpInst.addOperand(Inst.getOperand(5));
6089 Inst = TmpInst;
6090 return true;
6091 }
6092
Jim Grosbach3a678af2012-01-23 21:53:26 +00006093 case ARM::VLD3LNdWB_fixed_Asm_8:
6094 case ARM::VLD3LNdWB_fixed_Asm_16:
6095 case ARM::VLD3LNdWB_fixed_Asm_32:
6096 case ARM::VLD3LNqWB_fixed_Asm_16:
6097 case ARM::VLD3LNqWB_fixed_Asm_32: {
6098 MCInst TmpInst;
6099 // Shuffle the operands around so the lane index operand is in the
6100 // right place.
6101 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006102 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006103 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6104 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6105 Spacing));
6106 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006107 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006108 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6109 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6110 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6111 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6112 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6113 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6114 Spacing));
6115 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006116 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006117 TmpInst.addOperand(Inst.getOperand(1)); // lane
6118 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6119 TmpInst.addOperand(Inst.getOperand(5));
6120 Inst = TmpInst;
6121 return true;
6122 }
6123
Jim Grosbache983a132012-01-24 18:37:25 +00006124 case ARM::VLD4LNdWB_fixed_Asm_8:
6125 case ARM::VLD4LNdWB_fixed_Asm_16:
6126 case ARM::VLD4LNdWB_fixed_Asm_32:
6127 case ARM::VLD4LNqWB_fixed_Asm_16:
6128 case ARM::VLD4LNqWB_fixed_Asm_32: {
6129 MCInst TmpInst;
6130 // Shuffle the operands around so the lane index operand is in the
6131 // right place.
6132 unsigned Spacing;
6133 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6134 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6135 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6136 Spacing));
6137 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6138 Spacing * 2));
6139 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6140 Spacing * 3));
6141 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6142 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6143 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6144 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6145 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6146 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6147 Spacing));
6148 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6149 Spacing * 2));
6150 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6151 Spacing * 3));
6152 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 }
6158
Jim Grosbach8b31f952012-01-23 19:39:08 +00006159 case ARM::VLD1LNdAsm_8:
6160 case ARM::VLD1LNdAsm_16:
6161 case ARM::VLD1LNdAsm_32: {
Jim Grosbach7636bf62011-12-02 00:35:16 +00006162 MCInst TmpInst;
6163 // Shuffle the operands around so the lane index operand is in the
6164 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006165 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006166 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach7636bf62011-12-02 00:35:16 +00006167 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6168 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6169 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6170 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6171 TmpInst.addOperand(Inst.getOperand(1)); // lane
6172 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6173 TmpInst.addOperand(Inst.getOperand(5));
6174 Inst = TmpInst;
6175 return true;
6176 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006177
Jim Grosbach8b31f952012-01-23 19:39:08 +00006178 case ARM::VLD2LNdAsm_8:
6179 case ARM::VLD2LNdAsm_16:
6180 case ARM::VLD2LNdAsm_32:
6181 case ARM::VLD2LNqAsm_16:
6182 case ARM::VLD2LNqAsm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006183 MCInst TmpInst;
6184 // Shuffle the operands around so the lane index operand is in the
6185 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006186 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006187 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006188 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006189 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6190 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006191 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6192 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6193 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006194 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6195 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006196 TmpInst.addOperand(Inst.getOperand(1)); // lane
6197 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6198 TmpInst.addOperand(Inst.getOperand(5));
6199 Inst = TmpInst;
6200 return true;
6201 }
Jim Grosbach3a678af2012-01-23 21:53:26 +00006202
6203 case ARM::VLD3LNdAsm_8:
6204 case ARM::VLD3LNdAsm_16:
6205 case ARM::VLD3LNdAsm_32:
6206 case ARM::VLD3LNqAsm_16:
6207 case ARM::VLD3LNqAsm_32: {
6208 MCInst TmpInst;
6209 // Shuffle the operands around so the lane index operand is in the
6210 // right place.
6211 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006212 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006213 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6214 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6215 Spacing));
6216 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006217 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006218 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6219 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6220 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6221 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6222 Spacing));
6223 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006224 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006225 TmpInst.addOperand(Inst.getOperand(1)); // lane
6226 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6227 TmpInst.addOperand(Inst.getOperand(5));
6228 Inst = TmpInst;
6229 return true;
6230 }
6231
Jim Grosbache983a132012-01-24 18:37:25 +00006232 case ARM::VLD4LNdAsm_8:
6233 case ARM::VLD4LNdAsm_16:
6234 case ARM::VLD4LNdAsm_32:
6235 case ARM::VLD4LNqAsm_16:
6236 case ARM::VLD4LNqAsm_32: {
6237 MCInst TmpInst;
6238 // Shuffle the operands around so the lane index operand is in the
6239 // right place.
6240 unsigned Spacing;
6241 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6242 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6243 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6244 Spacing));
6245 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6246 Spacing * 2));
6247 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6248 Spacing * 3));
6249 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6250 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6251 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6252 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6253 Spacing));
6254 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6255 Spacing * 2));
6256 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6257 Spacing * 3));
6258 TmpInst.addOperand(Inst.getOperand(1)); // lane
6259 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6260 TmpInst.addOperand(Inst.getOperand(5));
6261 Inst = TmpInst;
6262 return true;
6263 }
6264
Jim Grosbach5e59f7e2012-01-24 23:47:04 +00006265 // VLD3DUP single 3-element structure to all lanes instructions.
6266 case ARM::VLD3DUPdAsm_8:
6267 case ARM::VLD3DUPdAsm_16:
6268 case ARM::VLD3DUPdAsm_32:
6269 case ARM::VLD3DUPqAsm_8:
6270 case ARM::VLD3DUPqAsm_16:
6271 case ARM::VLD3DUPqAsm_32: {
6272 MCInst TmpInst;
6273 unsigned Spacing;
6274 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6275 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6276 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6277 Spacing));
6278 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6279 Spacing * 2));
6280 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6281 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6282 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6283 TmpInst.addOperand(Inst.getOperand(4));
6284 Inst = TmpInst;
6285 return true;
6286 }
6287
6288 case ARM::VLD3DUPdWB_fixed_Asm_8:
6289 case ARM::VLD3DUPdWB_fixed_Asm_16:
6290 case ARM::VLD3DUPdWB_fixed_Asm_32:
6291 case ARM::VLD3DUPqWB_fixed_Asm_8:
6292 case ARM::VLD3DUPqWB_fixed_Asm_16:
6293 case ARM::VLD3DUPqWB_fixed_Asm_32: {
6294 MCInst TmpInst;
6295 unsigned Spacing;
6296 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6297 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6298 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6299 Spacing));
6300 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6301 Spacing * 2));
6302 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6303 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6304 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6305 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6306 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6307 TmpInst.addOperand(Inst.getOperand(4));
6308 Inst = TmpInst;
6309 return true;
6310 }
6311
6312 case ARM::VLD3DUPdWB_register_Asm_8:
6313 case ARM::VLD3DUPdWB_register_Asm_16:
6314 case ARM::VLD3DUPdWB_register_Asm_32:
6315 case ARM::VLD3DUPqWB_register_Asm_8:
6316 case ARM::VLD3DUPqWB_register_Asm_16:
6317 case ARM::VLD3DUPqWB_register_Asm_32: {
6318 MCInst TmpInst;
6319 unsigned Spacing;
6320 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6321 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6322 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6323 Spacing));
6324 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6325 Spacing * 2));
6326 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6327 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6328 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6329 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6330 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6331 TmpInst.addOperand(Inst.getOperand(5));
6332 Inst = TmpInst;
6333 return true;
6334 }
6335
Jim Grosbachc387fc62012-01-23 23:20:46 +00006336 // VLD3 multiple 3-element structure instructions.
6337 case ARM::VLD3dAsm_8:
6338 case ARM::VLD3dAsm_16:
6339 case ARM::VLD3dAsm_32:
6340 case ARM::VLD3qAsm_8:
6341 case ARM::VLD3qAsm_16:
6342 case ARM::VLD3qAsm_32: {
6343 MCInst TmpInst;
6344 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006345 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00006346 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6347 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6348 Spacing));
6349 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6350 Spacing * 2));
6351 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6352 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6353 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6354 TmpInst.addOperand(Inst.getOperand(4));
6355 Inst = TmpInst;
6356 return true;
6357 }
6358
6359 case ARM::VLD3dWB_fixed_Asm_8:
6360 case ARM::VLD3dWB_fixed_Asm_16:
6361 case ARM::VLD3dWB_fixed_Asm_32:
6362 case ARM::VLD3qWB_fixed_Asm_8:
6363 case ARM::VLD3qWB_fixed_Asm_16:
6364 case ARM::VLD3qWB_fixed_Asm_32: {
6365 MCInst TmpInst;
6366 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006367 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00006368 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6369 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6370 Spacing));
6371 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6372 Spacing * 2));
6373 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6374 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6375 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6376 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6377 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6378 TmpInst.addOperand(Inst.getOperand(4));
6379 Inst = TmpInst;
6380 return true;
6381 }
6382
6383 case ARM::VLD3dWB_register_Asm_8:
6384 case ARM::VLD3dWB_register_Asm_16:
6385 case ARM::VLD3dWB_register_Asm_32:
6386 case ARM::VLD3qWB_register_Asm_8:
6387 case ARM::VLD3qWB_register_Asm_16:
6388 case ARM::VLD3qWB_register_Asm_32: {
6389 MCInst TmpInst;
6390 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006391 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00006392 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6393 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6394 Spacing));
6395 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6396 Spacing * 2));
6397 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6398 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6399 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6400 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6401 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6402 TmpInst.addOperand(Inst.getOperand(5));
6403 Inst = TmpInst;
6404 return true;
6405 }
6406
Jim Grosbacha57a36a2012-01-25 00:01:08 +00006407 // VLD4DUP single 3-element structure to all lanes instructions.
6408 case ARM::VLD4DUPdAsm_8:
6409 case ARM::VLD4DUPdAsm_16:
6410 case ARM::VLD4DUPdAsm_32:
6411 case ARM::VLD4DUPqAsm_8:
6412 case ARM::VLD4DUPqAsm_16:
6413 case ARM::VLD4DUPqAsm_32: {
6414 MCInst TmpInst;
6415 unsigned Spacing;
6416 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6417 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6418 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6419 Spacing));
6420 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6421 Spacing * 2));
6422 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6423 Spacing * 3));
6424 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6425 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6426 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6427 TmpInst.addOperand(Inst.getOperand(4));
6428 Inst = TmpInst;
6429 return true;
6430 }
6431
6432 case ARM::VLD4DUPdWB_fixed_Asm_8:
6433 case ARM::VLD4DUPdWB_fixed_Asm_16:
6434 case ARM::VLD4DUPdWB_fixed_Asm_32:
6435 case ARM::VLD4DUPqWB_fixed_Asm_8:
6436 case ARM::VLD4DUPqWB_fixed_Asm_16:
6437 case ARM::VLD4DUPqWB_fixed_Asm_32: {
6438 MCInst TmpInst;
6439 unsigned Spacing;
6440 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6441 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6442 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6443 Spacing));
6444 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6445 Spacing * 2));
6446 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6447 Spacing * 3));
6448 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6449 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6450 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6451 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6452 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6453 TmpInst.addOperand(Inst.getOperand(4));
6454 Inst = TmpInst;
6455 return true;
6456 }
6457
6458 case ARM::VLD4DUPdWB_register_Asm_8:
6459 case ARM::VLD4DUPdWB_register_Asm_16:
6460 case ARM::VLD4DUPdWB_register_Asm_32:
6461 case ARM::VLD4DUPqWB_register_Asm_8:
6462 case ARM::VLD4DUPqWB_register_Asm_16:
6463 case ARM::VLD4DUPqWB_register_Asm_32: {
6464 MCInst TmpInst;
6465 unsigned Spacing;
6466 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6467 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6468 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6469 Spacing));
6470 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6471 Spacing * 2));
6472 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6473 Spacing * 3));
6474 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6475 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6476 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6477 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6478 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6479 TmpInst.addOperand(Inst.getOperand(5));
6480 Inst = TmpInst;
6481 return true;
6482 }
6483
6484 // VLD4 multiple 4-element structure instructions.
Jim Grosbach8abe7e32012-01-24 00:43:17 +00006485 case ARM::VLD4dAsm_8:
6486 case ARM::VLD4dAsm_16:
6487 case ARM::VLD4dAsm_32:
6488 case ARM::VLD4qAsm_8:
6489 case ARM::VLD4qAsm_16:
6490 case ARM::VLD4qAsm_32: {
6491 MCInst TmpInst;
6492 unsigned Spacing;
6493 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6494 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6495 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6496 Spacing));
6497 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6498 Spacing * 2));
6499 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6500 Spacing * 3));
6501 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6502 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6503 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6504 TmpInst.addOperand(Inst.getOperand(4));
6505 Inst = TmpInst;
6506 return true;
6507 }
6508
6509 case ARM::VLD4dWB_fixed_Asm_8:
6510 case ARM::VLD4dWB_fixed_Asm_16:
6511 case ARM::VLD4dWB_fixed_Asm_32:
6512 case ARM::VLD4qWB_fixed_Asm_8:
6513 case ARM::VLD4qWB_fixed_Asm_16:
6514 case ARM::VLD4qWB_fixed_Asm_32: {
6515 MCInst TmpInst;
6516 unsigned Spacing;
6517 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6518 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6519 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6520 Spacing));
6521 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6522 Spacing * 2));
6523 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6524 Spacing * 3));
6525 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6526 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6527 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6528 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6529 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6530 TmpInst.addOperand(Inst.getOperand(4));
6531 Inst = TmpInst;
6532 return true;
6533 }
6534
6535 case ARM::VLD4dWB_register_Asm_8:
6536 case ARM::VLD4dWB_register_Asm_16:
6537 case ARM::VLD4dWB_register_Asm_32:
6538 case ARM::VLD4qWB_register_Asm_8:
6539 case ARM::VLD4qWB_register_Asm_16:
6540 case ARM::VLD4qWB_register_Asm_32: {
6541 MCInst TmpInst;
6542 unsigned Spacing;
6543 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6544 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6545 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6546 Spacing));
6547 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6548 Spacing * 2));
6549 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6550 Spacing * 3));
6551 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6552 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6553 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6554 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6555 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6556 TmpInst.addOperand(Inst.getOperand(5));
6557 Inst = TmpInst;
6558 return true;
6559 }
6560
Jim Grosbachd7433e22012-01-23 23:45:44 +00006561 // VST3 multiple 3-element structure instructions.
6562 case ARM::VST3dAsm_8:
6563 case ARM::VST3dAsm_16:
6564 case ARM::VST3dAsm_32:
6565 case ARM::VST3qAsm_8:
6566 case ARM::VST3qAsm_16:
6567 case ARM::VST3qAsm_32: {
6568 MCInst TmpInst;
6569 unsigned Spacing;
6570 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6571 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6572 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6573 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6574 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6575 Spacing));
6576 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6577 Spacing * 2));
6578 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6579 TmpInst.addOperand(Inst.getOperand(4));
6580 Inst = TmpInst;
6581 return true;
6582 }
6583
6584 case ARM::VST3dWB_fixed_Asm_8:
6585 case ARM::VST3dWB_fixed_Asm_16:
6586 case ARM::VST3dWB_fixed_Asm_32:
6587 case ARM::VST3qWB_fixed_Asm_8:
6588 case ARM::VST3qWB_fixed_Asm_16:
6589 case ARM::VST3qWB_fixed_Asm_32: {
6590 MCInst TmpInst;
6591 unsigned Spacing;
6592 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6593 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6594 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6595 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6596 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6597 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6598 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6599 Spacing));
6600 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6601 Spacing * 2));
6602 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6603 TmpInst.addOperand(Inst.getOperand(4));
6604 Inst = TmpInst;
6605 return true;
6606 }
6607
6608 case ARM::VST3dWB_register_Asm_8:
6609 case ARM::VST3dWB_register_Asm_16:
6610 case ARM::VST3dWB_register_Asm_32:
6611 case ARM::VST3qWB_register_Asm_8:
6612 case ARM::VST3qWB_register_Asm_16:
6613 case ARM::VST3qWB_register_Asm_32: {
6614 MCInst TmpInst;
6615 unsigned Spacing;
6616 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6617 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6618 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6619 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6620 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6621 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6622 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6623 Spacing));
6624 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6625 Spacing * 2));
6626 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6627 TmpInst.addOperand(Inst.getOperand(5));
6628 Inst = TmpInst;
6629 return true;
6630 }
6631
Jim Grosbach539aab72012-01-24 00:58:13 +00006632 // VST4 multiple 3-element structure instructions.
6633 case ARM::VST4dAsm_8:
6634 case ARM::VST4dAsm_16:
6635 case ARM::VST4dAsm_32:
6636 case ARM::VST4qAsm_8:
6637 case ARM::VST4qAsm_16:
6638 case ARM::VST4qAsm_32: {
6639 MCInst TmpInst;
6640 unsigned Spacing;
6641 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6642 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6643 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6644 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6645 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6646 Spacing));
6647 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6648 Spacing * 2));
6649 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6650 Spacing * 3));
6651 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6652 TmpInst.addOperand(Inst.getOperand(4));
6653 Inst = TmpInst;
6654 return true;
6655 }
6656
6657 case ARM::VST4dWB_fixed_Asm_8:
6658 case ARM::VST4dWB_fixed_Asm_16:
6659 case ARM::VST4dWB_fixed_Asm_32:
6660 case ARM::VST4qWB_fixed_Asm_8:
6661 case ARM::VST4qWB_fixed_Asm_16:
6662 case ARM::VST4qWB_fixed_Asm_32: {
6663 MCInst TmpInst;
6664 unsigned Spacing;
6665 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6666 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6667 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6668 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6669 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6670 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6671 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6672 Spacing));
6673 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6674 Spacing * 2));
6675 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6676 Spacing * 3));
6677 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6678 TmpInst.addOperand(Inst.getOperand(4));
6679 Inst = TmpInst;
6680 return true;
6681 }
6682
6683 case ARM::VST4dWB_register_Asm_8:
6684 case ARM::VST4dWB_register_Asm_16:
6685 case ARM::VST4dWB_register_Asm_32:
6686 case ARM::VST4qWB_register_Asm_8:
6687 case ARM::VST4qWB_register_Asm_16:
6688 case ARM::VST4qWB_register_Asm_32: {
6689 MCInst TmpInst;
6690 unsigned Spacing;
6691 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6692 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6693 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6694 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6695 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6696 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6697 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6698 Spacing));
6699 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6700 Spacing * 2));
6701 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6702 Spacing * 3));
6703 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6704 TmpInst.addOperand(Inst.getOperand(5));
6705 Inst = TmpInst;
6706 return true;
6707 }
6708
Jim Grosbacha5378eb2012-04-11 00:15:16 +00006709 // Handle encoding choice for the shift-immediate instructions.
6710 case ARM::t2LSLri:
6711 case ARM::t2LSRri:
6712 case ARM::t2ASRri: {
6713 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6714 Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
6715 Inst.getOperand(5).getReg() == (inITBlock() ? 0 : ARM::CPSR) &&
6716 !(static_cast<ARMOperand*>(Operands[3])->isToken() &&
6717 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w")) {
6718 unsigned NewOpc;
6719 switch (Inst.getOpcode()) {
6720 default: llvm_unreachable("unexpected opcode");
6721 case ARM::t2LSLri: NewOpc = ARM::tLSLri; break;
6722 case ARM::t2LSRri: NewOpc = ARM::tLSRri; break;
6723 case ARM::t2ASRri: NewOpc = ARM::tASRri; break;
6724 }
6725 // The Thumb1 operands aren't in the same order. Awesome, eh?
6726 MCInst TmpInst;
6727 TmpInst.setOpcode(NewOpc);
6728 TmpInst.addOperand(Inst.getOperand(0));
6729 TmpInst.addOperand(Inst.getOperand(5));
6730 TmpInst.addOperand(Inst.getOperand(1));
6731 TmpInst.addOperand(Inst.getOperand(2));
6732 TmpInst.addOperand(Inst.getOperand(3));
6733 TmpInst.addOperand(Inst.getOperand(4));
6734 Inst = TmpInst;
6735 return true;
6736 }
6737 return false;
6738 }
6739
Jim Grosbach863d2af2011-12-13 22:45:11 +00006740 // Handle the Thumb2 mode MOV complex aliases.
Jim Grosbach2cc5cda2011-12-21 20:54:00 +00006741 case ARM::t2MOVsr:
6742 case ARM::t2MOVSsr: {
6743 // Which instruction to expand to depends on the CCOut operand and
6744 // whether we're in an IT block if the register operands are low
6745 // registers.
6746 bool isNarrow = false;
6747 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6748 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6749 isARMLowRegister(Inst.getOperand(2).getReg()) &&
6750 Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
6751 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsr))
6752 isNarrow = true;
6753 MCInst TmpInst;
6754 unsigned newOpc;
6755 switch(ARM_AM::getSORegShOp(Inst.getOperand(3).getImm())) {
6756 default: llvm_unreachable("unexpected opcode!");
6757 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRrr : ARM::t2ASRrr; break;
6758 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRrr : ARM::t2LSRrr; break;
6759 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLrr : ARM::t2LSLrr; break;
6760 case ARM_AM::ror: newOpc = isNarrow ? ARM::tROR : ARM::t2RORrr; break;
6761 }
6762 TmpInst.setOpcode(newOpc);
6763 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6764 if (isNarrow)
6765 TmpInst.addOperand(MCOperand::CreateReg(
6766 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6767 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6768 TmpInst.addOperand(Inst.getOperand(2)); // Rm
6769 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6770 TmpInst.addOperand(Inst.getOperand(5));
6771 if (!isNarrow)
6772 TmpInst.addOperand(MCOperand::CreateReg(
6773 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6774 Inst = TmpInst;
6775 return true;
6776 }
Jim Grosbach863d2af2011-12-13 22:45:11 +00006777 case ARM::t2MOVsi:
6778 case ARM::t2MOVSsi: {
6779 // Which instruction to expand to depends on the CCOut operand and
6780 // whether we're in an IT block if the register operands are low
6781 // registers.
6782 bool isNarrow = false;
6783 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6784 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6785 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
6786 isNarrow = true;
6787 MCInst TmpInst;
6788 unsigned newOpc;
6789 switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
6790 default: llvm_unreachable("unexpected opcode!");
6791 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
6792 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
6793 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
6794 case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
Jim Grosbach520dc782011-12-21 21:04:19 +00006795 case ARM_AM::rrx: isNarrow = false; newOpc = ARM::t2RRX; break;
Jim Grosbach863d2af2011-12-13 22:45:11 +00006796 }
Benjamin Kramerd9b0b022012-06-02 10:20:22 +00006797 unsigned Amount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
6798 if (Amount == 32) Amount = 0;
Jim Grosbach863d2af2011-12-13 22:45:11 +00006799 TmpInst.setOpcode(newOpc);
6800 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6801 if (isNarrow)
6802 TmpInst.addOperand(MCOperand::CreateReg(
6803 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6804 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbach520dc782011-12-21 21:04:19 +00006805 if (newOpc != ARM::t2RRX)
Benjamin Kramerd9b0b022012-06-02 10:20:22 +00006806 TmpInst.addOperand(MCOperand::CreateImm(Amount));
Jim Grosbach863d2af2011-12-13 22:45:11 +00006807 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6808 TmpInst.addOperand(Inst.getOperand(4));
6809 if (!isNarrow)
6810 TmpInst.addOperand(MCOperand::CreateReg(
6811 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6812 Inst = TmpInst;
6813 return true;
6814 }
6815 // Handle the ARM mode MOV complex aliases.
Jim Grosbach23f22072011-11-16 18:31:45 +00006816 case ARM::ASRr:
6817 case ARM::LSRr:
6818 case ARM::LSLr:
6819 case ARM::RORr: {
6820 ARM_AM::ShiftOpc ShiftTy;
6821 switch(Inst.getOpcode()) {
6822 default: llvm_unreachable("unexpected opcode!");
6823 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
6824 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
6825 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
6826 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
6827 }
Jim Grosbach23f22072011-11-16 18:31:45 +00006828 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
6829 MCInst TmpInst;
6830 TmpInst.setOpcode(ARM::MOVsr);
6831 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6832 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6833 TmpInst.addOperand(Inst.getOperand(2)); // Rm
6834 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6835 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6836 TmpInst.addOperand(Inst.getOperand(4));
6837 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6838 Inst = TmpInst;
6839 return true;
6840 }
Jim Grosbachee10ff82011-11-10 19:18:01 +00006841 case ARM::ASRi:
6842 case ARM::LSRi:
6843 case ARM::LSLi:
6844 case ARM::RORi: {
6845 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachee10ff82011-11-10 19:18:01 +00006846 switch(Inst.getOpcode()) {
6847 default: llvm_unreachable("unexpected opcode!");
6848 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
6849 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
6850 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
6851 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
6852 }
6853 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach48b368b2011-11-16 19:05:59 +00006854 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachee10ff82011-11-10 19:18:01 +00006855 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
Richard Bartonb56e4112012-04-25 18:00:18 +00006856 // A shift by 32 should be encoded as 0 when permitted
6857 if (Amt == 32 && (ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr))
6858 Amt = 0;
Jim Grosbachee10ff82011-11-10 19:18:01 +00006859 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach71810ab2011-11-10 16:44:55 +00006860 MCInst TmpInst;
Jim Grosbachee10ff82011-11-10 19:18:01 +00006861 TmpInst.setOpcode(Opc);
Jim Grosbach71810ab2011-11-10 16:44:55 +00006862 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6863 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachee10ff82011-11-10 19:18:01 +00006864 if (Opc == ARM::MOVsi)
6865 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach71810ab2011-11-10 16:44:55 +00006866 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6867 TmpInst.addOperand(Inst.getOperand(4));
6868 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6869 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006870 return true;
Jim Grosbach71810ab2011-11-10 16:44:55 +00006871 }
Jim Grosbach48b368b2011-11-16 19:05:59 +00006872 case ARM::RRXi: {
6873 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
6874 MCInst TmpInst;
6875 TmpInst.setOpcode(ARM::MOVsi);
6876 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6877 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6878 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6879 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6880 TmpInst.addOperand(Inst.getOperand(3));
6881 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
6882 Inst = TmpInst;
6883 return true;
6884 }
Jim Grosbach0352b462011-11-10 23:58:34 +00006885 case ARM::t2LDMIA_UPD: {
6886 // If this is a load of a single register, then we should use
6887 // a post-indexed LDR instruction instead, per the ARM ARM.
6888 if (Inst.getNumOperands() != 5)
6889 return false;
6890 MCInst TmpInst;
6891 TmpInst.setOpcode(ARM::t2LDR_POST);
6892 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6893 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6894 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6895 TmpInst.addOperand(MCOperand::CreateImm(4));
6896 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6897 TmpInst.addOperand(Inst.getOperand(3));
6898 Inst = TmpInst;
6899 return true;
6900 }
6901 case ARM::t2STMDB_UPD: {
6902 // If this is a store of a single register, then we should use
6903 // a pre-indexed STR instruction instead, per the ARM ARM.
6904 if (Inst.getNumOperands() != 5)
6905 return false;
6906 MCInst TmpInst;
6907 TmpInst.setOpcode(ARM::t2STR_PRE);
6908 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6909 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6910 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6911 TmpInst.addOperand(MCOperand::CreateImm(-4));
6912 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6913 TmpInst.addOperand(Inst.getOperand(3));
6914 Inst = TmpInst;
6915 return true;
6916 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00006917 case ARM::LDMIA_UPD:
6918 // If this is a load of a single register via a 'pop', then we should use
6919 // a post-indexed LDR instruction instead, per the ARM ARM.
6920 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
6921 Inst.getNumOperands() == 5) {
6922 MCInst TmpInst;
6923 TmpInst.setOpcode(ARM::LDR_POST_IMM);
6924 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6925 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6926 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6927 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
6928 TmpInst.addOperand(MCOperand::CreateImm(4));
6929 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6930 TmpInst.addOperand(Inst.getOperand(3));
6931 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006932 return true;
Jim Grosbachf8fce712011-08-11 17:35:48 +00006933 }
6934 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00006935 case ARM::STMDB_UPD:
6936 // If this is a store of a single register via a 'push', then we should use
6937 // a pre-indexed STR instruction instead, per the ARM ARM.
6938 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
6939 Inst.getNumOperands() == 5) {
6940 MCInst TmpInst;
6941 TmpInst.setOpcode(ARM::STR_PRE_IMM);
6942 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6943 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6944 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
6945 TmpInst.addOperand(MCOperand::CreateImm(-4));
6946 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6947 TmpInst.addOperand(Inst.getOperand(3));
6948 Inst = TmpInst;
6949 }
6950 break;
Jim Grosbachda847862011-12-05 21:06:26 +00006951 case ARM::t2ADDri12:
6952 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
6953 // mnemonic was used (not "addw"), encoding T3 is preferred.
6954 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
6955 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
6956 break;
6957 Inst.setOpcode(ARM::t2ADDri);
6958 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
6959 break;
6960 case ARM::t2SUBri12:
6961 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
6962 // mnemonic was used (not "subw"), encoding T3 is preferred.
6963 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
6964 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
6965 break;
6966 Inst.setOpcode(ARM::t2SUBri);
6967 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
6968 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006969 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00006970 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6971 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6972 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6973 // to encoding T1 if <Rd> is omitted."
Jim Grosbachc0164f82012-03-30 16:31:31 +00006974 if ((unsigned)Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006975 Inst.setOpcode(ARM::tADDi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006976 return true;
6977 }
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006978 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00006979 case ARM::tSUBi8:
6980 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6981 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6982 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6983 // to encoding T1 if <Rd> is omitted."
Jim Grosbachc0164f82012-03-30 16:31:31 +00006984 if ((unsigned)Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachf67e8552011-09-16 22:58:42 +00006985 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006986 return true;
6987 }
Jim Grosbachf67e8552011-09-16 22:58:42 +00006988 break;
Jim Grosbach2d30d942012-03-30 17:20:40 +00006989 case ARM::t2ADDri:
6990 case ARM::t2SUBri: {
6991 // If the destination and first source operand are the same, and
6992 // the flags are compatible with the current IT status, use encoding T2
6993 // instead of T3. For compatibility with the system 'as'. Make sure the
6994 // wide encoding wasn't explicit.
6995 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
Jim Grosbach8f1148b2012-03-30 18:39:43 +00006996 !isARMLowRegister(Inst.getOperand(0).getReg()) ||
Jim Grosbach2d30d942012-03-30 17:20:40 +00006997 (unsigned)Inst.getOperand(2).getImm() > 255 ||
6998 ((!inITBlock() && Inst.getOperand(5).getReg() != ARM::CPSR) ||
6999 (inITBlock() && Inst.getOperand(5).getReg() != 0)) ||
7000 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
7001 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
7002 break;
7003 MCInst TmpInst;
7004 TmpInst.setOpcode(Inst.getOpcode() == ARM::t2ADDri ?
7005 ARM::tADDi8 : ARM::tSUBi8);
7006 TmpInst.addOperand(Inst.getOperand(0));
7007 TmpInst.addOperand(Inst.getOperand(5));
7008 TmpInst.addOperand(Inst.getOperand(0));
7009 TmpInst.addOperand(Inst.getOperand(2));
7010 TmpInst.addOperand(Inst.getOperand(3));
7011 TmpInst.addOperand(Inst.getOperand(4));
7012 Inst = TmpInst;
7013 return true;
7014 }
Jim Grosbach927b9df2011-12-05 22:16:39 +00007015 case ARM::t2ADDrr: {
7016 // If the destination and first source operand are the same, and
7017 // there's no setting of the flags, use encoding T2 instead of T3.
7018 // Note that this is only for ADD, not SUB. This mirrors the system
7019 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
7020 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
7021 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbach713c7022011-12-05 22:27:04 +00007022 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
7023 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbach927b9df2011-12-05 22:16:39 +00007024 break;
7025 MCInst TmpInst;
7026 TmpInst.setOpcode(ARM::tADDhirr);
7027 TmpInst.addOperand(Inst.getOperand(0));
7028 TmpInst.addOperand(Inst.getOperand(0));
7029 TmpInst.addOperand(Inst.getOperand(2));
7030 TmpInst.addOperand(Inst.getOperand(3));
7031 TmpInst.addOperand(Inst.getOperand(4));
7032 Inst = TmpInst;
7033 return true;
7034 }
Jim Grosbacha9cc08f2012-04-27 23:51:36 +00007035 case ARM::tADDrSP: {
7036 // If the non-SP source operand and the destination operand are not the
7037 // same, we need to use the 32-bit encoding if it's available.
7038 if (Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg()) {
7039 Inst.setOpcode(ARM::t2ADDrr);
7040 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
7041 return true;
7042 }
7043 break;
7044 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00007045 case ARM::tB:
7046 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00007047 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson51f6a7a2011-09-09 21:48:23 +00007048 Inst.setOpcode(ARM::tBcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00007049 return true;
7050 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00007051 break;
7052 case ARM::t2B:
7053 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00007054 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson51f6a7a2011-09-09 21:48:23 +00007055 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00007056 return true;
7057 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00007058 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00007059 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00007060 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbach83ec8772011-11-10 23:42:14 +00007061 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbachc0755102011-08-31 21:17:31 +00007062 Inst.setOpcode(ARM::t2B);
Jim Grosbach83ec8772011-11-10 23:42:14 +00007063 return true;
7064 }
Jim Grosbachc0755102011-08-31 21:17:31 +00007065 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00007066 case ARM::tBcc:
7067 // If the conditional is AL, we really want tB.
Jim Grosbach83ec8772011-11-10 23:42:14 +00007068 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbach395b4532011-08-17 22:57:40 +00007069 Inst.setOpcode(ARM::tB);
Jim Grosbach83ec8772011-11-10 23:42:14 +00007070 return true;
7071 }
Jim Grosbach3ce23d32011-08-18 16:08:39 +00007072 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00007073 case ARM::tLDMIA: {
7074 // If the register list contains any high registers, or if the writeback
7075 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
7076 // instead if we're in Thumb2. Otherwise, this should have generated
7077 // an error in validateInstruction().
7078 unsigned Rn = Inst.getOperand(0).getReg();
7079 bool hasWritebackToken =
7080 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
7081 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
7082 bool listContainsBase;
7083 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
7084 (!listContainsBase && !hasWritebackToken) ||
7085 (listContainsBase && hasWritebackToken)) {
7086 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
7087 assert (isThumbTwo());
7088 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
7089 // If we're switching to the updating version, we need to insert
7090 // the writeback tied operand.
7091 if (hasWritebackToken)
7092 Inst.insert(Inst.begin(),
7093 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbach83ec8772011-11-10 23:42:14 +00007094 return true;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00007095 }
7096 break;
7097 }
Jim Grosbach8213c962011-09-16 20:50:13 +00007098 case ARM::tSTMIA_UPD: {
7099 // If the register list contains any high registers, we need to use
7100 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
7101 // should have generated an error in validateInstruction().
7102 unsigned Rn = Inst.getOperand(0).getReg();
7103 bool listContainsBase;
7104 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
7105 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
7106 assert (isThumbTwo());
7107 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbach83ec8772011-11-10 23:42:14 +00007108 return true;
Jim Grosbach8213c962011-09-16 20:50:13 +00007109 }
7110 break;
7111 }
Jim Grosbach54026372011-11-10 23:17:11 +00007112 case ARM::tPOP: {
7113 bool listContainsBase;
7114 // If the register list contains any high registers, we need to use
7115 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
7116 // should have generated an error in validateInstruction().
7117 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00007118 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00007119 assert (isThumbTwo());
7120 Inst.setOpcode(ARM::t2LDMIA_UPD);
7121 // Add the base register and writeback operands.
7122 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
7123 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00007124 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00007125 }
7126 case ARM::tPUSH: {
7127 bool listContainsBase;
7128 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00007129 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00007130 assert (isThumbTwo());
7131 Inst.setOpcode(ARM::t2STMDB_UPD);
7132 // Add the base register and writeback operands.
7133 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
7134 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00007135 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00007136 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00007137 case ARM::t2MOVi: {
7138 // If we can use the 16-bit encoding and the user didn't explicitly
7139 // request the 32-bit variant, transform it here.
7140 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
Jim Grosbachc0164f82012-03-30 16:31:31 +00007141 (unsigned)Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00007142 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
7143 Inst.getOperand(4).getReg() == ARM::CPSR) ||
7144 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00007145 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
7146 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
7147 // The operands aren't in the same order for tMOVi8...
7148 MCInst TmpInst;
7149 TmpInst.setOpcode(ARM::tMOVi8);
7150 TmpInst.addOperand(Inst.getOperand(0));
7151 TmpInst.addOperand(Inst.getOperand(4));
7152 TmpInst.addOperand(Inst.getOperand(1));
7153 TmpInst.addOperand(Inst.getOperand(2));
7154 TmpInst.addOperand(Inst.getOperand(3));
7155 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00007156 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00007157 }
7158 break;
7159 }
7160 case ARM::t2MOVr: {
7161 // If we can use the 16-bit encoding and the user didn't explicitly
7162 // request the 32-bit variant, transform it here.
7163 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
7164 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7165 Inst.getOperand(2).getImm() == ARMCC::AL &&
7166 Inst.getOperand(4).getReg() == ARM::CPSR &&
7167 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
7168 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
7169 // The operands aren't the same for tMOV[S]r... (no cc_out)
7170 MCInst TmpInst;
7171 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
7172 TmpInst.addOperand(Inst.getOperand(0));
7173 TmpInst.addOperand(Inst.getOperand(1));
7174 TmpInst.addOperand(Inst.getOperand(2));
7175 TmpInst.addOperand(Inst.getOperand(3));
7176 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00007177 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00007178 }
7179 break;
7180 }
Jim Grosbach326efe52011-09-19 20:29:33 +00007181 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00007182 case ARM::t2SXTB:
7183 case ARM::t2UXTH:
7184 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00007185 // If we can use the 16-bit encoding and the user didn't explicitly
7186 // request the 32-bit variant, transform it here.
7187 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
7188 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7189 Inst.getOperand(2).getImm() == 0 &&
7190 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
7191 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00007192 unsigned NewOpc;
7193 switch (Inst.getOpcode()) {
7194 default: llvm_unreachable("Illegal opcode!");
7195 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
7196 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
7197 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
7198 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
7199 }
Jim Grosbach326efe52011-09-19 20:29:33 +00007200 // The operands aren't the same for thumb1 (no rotate operand).
7201 MCInst TmpInst;
7202 TmpInst.setOpcode(NewOpc);
7203 TmpInst.addOperand(Inst.getOperand(0));
7204 TmpInst.addOperand(Inst.getOperand(1));
7205 TmpInst.addOperand(Inst.getOperand(3));
7206 TmpInst.addOperand(Inst.getOperand(4));
7207 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00007208 return true;
Jim Grosbach326efe52011-09-19 20:29:33 +00007209 }
7210 break;
7211 }
Jim Grosbach04b5d932011-12-20 00:59:38 +00007212 case ARM::MOVsi: {
7213 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm());
Richard Bartonb56e4112012-04-25 18:00:18 +00007214 // rrx shifts and asr/lsr of #32 is encoded as 0
7215 if (SOpc == ARM_AM::rrx || SOpc == ARM_AM::asr || SOpc == ARM_AM::lsr)
7216 return false;
Jim Grosbach04b5d932011-12-20 00:59:38 +00007217 if (ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()) == 0) {
7218 // Shifting by zero is accepted as a vanilla 'MOVr'
7219 MCInst TmpInst;
7220 TmpInst.setOpcode(ARM::MOVr);
7221 TmpInst.addOperand(Inst.getOperand(0));
7222 TmpInst.addOperand(Inst.getOperand(1));
7223 TmpInst.addOperand(Inst.getOperand(3));
7224 TmpInst.addOperand(Inst.getOperand(4));
7225 TmpInst.addOperand(Inst.getOperand(5));
7226 Inst = TmpInst;
7227 return true;
7228 }
7229 return false;
7230 }
Jim Grosbach8d9550b2011-12-22 18:04:04 +00007231 case ARM::ANDrsi:
7232 case ARM::ORRrsi:
7233 case ARM::EORrsi:
7234 case ARM::BICrsi:
7235 case ARM::SUBrsi:
7236 case ARM::ADDrsi: {
7237 unsigned newOpc;
7238 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(3).getImm());
7239 if (SOpc == ARM_AM::rrx) return false;
7240 switch (Inst.getOpcode()) {
Craig Topperbc219812012-02-07 02:50:20 +00007241 default: llvm_unreachable("unexpected opcode!");
Jim Grosbach8d9550b2011-12-22 18:04:04 +00007242 case ARM::ANDrsi: newOpc = ARM::ANDrr; break;
7243 case ARM::ORRrsi: newOpc = ARM::ORRrr; break;
7244 case ARM::EORrsi: newOpc = ARM::EORrr; break;
7245 case ARM::BICrsi: newOpc = ARM::BICrr; break;
7246 case ARM::SUBrsi: newOpc = ARM::SUBrr; break;
7247 case ARM::ADDrsi: newOpc = ARM::ADDrr; break;
7248 }
7249 // If the shift is by zero, use the non-shifted instruction definition.
Richard Barton8ed97ef2012-07-09 16:31:14 +00007250 // The exception is for right shifts, where 0 == 32
7251 if (ARM_AM::getSORegOffset(Inst.getOperand(3).getImm()) == 0 &&
7252 !(SOpc == ARM_AM::lsr || SOpc == ARM_AM::asr)) {
Jim Grosbach8d9550b2011-12-22 18:04:04 +00007253 MCInst TmpInst;
7254 TmpInst.setOpcode(newOpc);
7255 TmpInst.addOperand(Inst.getOperand(0));
7256 TmpInst.addOperand(Inst.getOperand(1));
7257 TmpInst.addOperand(Inst.getOperand(2));
7258 TmpInst.addOperand(Inst.getOperand(4));
7259 TmpInst.addOperand(Inst.getOperand(5));
7260 TmpInst.addOperand(Inst.getOperand(6));
7261 Inst = TmpInst;
7262 return true;
7263 }
7264 return false;
7265 }
Jim Grosbach74423e32012-01-25 19:52:01 +00007266 case ARM::ITasm:
Jim Grosbach89df9962011-08-26 21:43:41 +00007267 case ARM::t2IT: {
7268 // The mask bits for all but the first condition are represented as
7269 // the low bit of the condition code value implies 't'. We currently
7270 // always have 1 implies 't', so XOR toggle the bits if the low bit
Richard Barton4d2f0772012-04-27 08:42:59 +00007271 // of the condition code is zero.
Jim Grosbach89df9962011-08-26 21:43:41 +00007272 MCOperand &MO = Inst.getOperand(1);
7273 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007274 unsigned OrigMask = Mask;
7275 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00007276 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00007277 assert(Mask && TZ <= 3 && "illegal IT mask value!");
7278 for (unsigned i = 3; i != TZ; --i)
7279 Mask ^= 1 << i;
Richard Barton4d2f0772012-04-27 08:42:59 +00007280 }
Jim Grosbach89df9962011-08-26 21:43:41 +00007281 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007282
7283 // Set up the IT block state according to the IT instruction we just
7284 // matched.
7285 assert(!inITBlock() && "nested IT blocks?!");
7286 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
7287 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
7288 ITState.CurPosition = 0;
7289 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00007290 break;
7291 }
Richard Barton2b6652f2012-07-09 16:12:24 +00007292 case ARM::t2LSLrr:
7293 case ARM::t2LSRrr:
7294 case ARM::t2ASRrr:
7295 case ARM::t2SBCrr:
7296 case ARM::t2RORrr:
7297 case ARM::t2BICrr:
7298 {
Richard Bartonc985e6e2012-07-09 16:14:28 +00007299 // Assemblers should use the narrow encodings of these instructions when permissible.
Richard Barton2b6652f2012-07-09 16:12:24 +00007300 if ((isARMLowRegister(Inst.getOperand(1).getReg()) &&
7301 isARMLowRegister(Inst.getOperand(2).getReg())) &&
7302 Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
Richard Barton874b8632012-07-09 18:30:56 +00007303 ((!inITBlock() && Inst.getOperand(5).getReg() == ARM::CPSR) ||
7304 (inITBlock() && Inst.getOperand(5).getReg() != ARM::CPSR)) &&
Richard Barton2b6652f2012-07-09 16:12:24 +00007305 (!static_cast<ARMOperand*>(Operands[3])->isToken() ||
7306 !static_cast<ARMOperand*>(Operands[3])->getToken().equals_lower(".w"))) {
7307 unsigned NewOpc;
7308 switch (Inst.getOpcode()) {
7309 default: llvm_unreachable("unexpected opcode");
7310 case ARM::t2LSLrr: NewOpc = ARM::tLSLrr; break;
7311 case ARM::t2LSRrr: NewOpc = ARM::tLSRrr; break;
7312 case ARM::t2ASRrr: NewOpc = ARM::tASRrr; break;
7313 case ARM::t2SBCrr: NewOpc = ARM::tSBC; break;
7314 case ARM::t2RORrr: NewOpc = ARM::tROR; break;
7315 case ARM::t2BICrr: NewOpc = ARM::tBIC; break;
7316 }
7317 MCInst TmpInst;
7318 TmpInst.setOpcode(NewOpc);
7319 TmpInst.addOperand(Inst.getOperand(0));
7320 TmpInst.addOperand(Inst.getOperand(5));
7321 TmpInst.addOperand(Inst.getOperand(1));
7322 TmpInst.addOperand(Inst.getOperand(2));
7323 TmpInst.addOperand(Inst.getOperand(3));
7324 TmpInst.addOperand(Inst.getOperand(4));
7325 Inst = TmpInst;
7326 return true;
7327 }
7328 return false;
7329 }
7330 case ARM::t2ANDrr:
7331 case ARM::t2EORrr:
7332 case ARM::t2ADCrr:
7333 case ARM::t2ORRrr:
7334 {
Richard Bartonc985e6e2012-07-09 16:14:28 +00007335 // Assemblers should use the narrow encodings of these instructions when permissible.
Richard Barton2b6652f2012-07-09 16:12:24 +00007336 // These instructions are special in that they are commutable, so shorter encodings
7337 // are available more often.
7338 if ((isARMLowRegister(Inst.getOperand(1).getReg()) &&
7339 isARMLowRegister(Inst.getOperand(2).getReg())) &&
7340 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() ||
7341 Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg()) &&
Richard Barton874b8632012-07-09 18:30:56 +00007342 ((!inITBlock() && Inst.getOperand(5).getReg() == ARM::CPSR) ||
7343 (inITBlock() && Inst.getOperand(5).getReg() != ARM::CPSR)) &&
Richard Barton2b6652f2012-07-09 16:12:24 +00007344 (!static_cast<ARMOperand*>(Operands[3])->isToken() ||
7345 !static_cast<ARMOperand*>(Operands[3])->getToken().equals_lower(".w"))) {
7346 unsigned NewOpc;
7347 switch (Inst.getOpcode()) {
7348 default: llvm_unreachable("unexpected opcode");
7349 case ARM::t2ADCrr: NewOpc = ARM::tADC; break;
7350 case ARM::t2ANDrr: NewOpc = ARM::tAND; break;
7351 case ARM::t2EORrr: NewOpc = ARM::tEOR; break;
7352 case ARM::t2ORRrr: NewOpc = ARM::tORR; break;
7353 }
7354 MCInst TmpInst;
7355 TmpInst.setOpcode(NewOpc);
7356 TmpInst.addOperand(Inst.getOperand(0));
7357 TmpInst.addOperand(Inst.getOperand(5));
7358 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()) {
7359 TmpInst.addOperand(Inst.getOperand(1));
7360 TmpInst.addOperand(Inst.getOperand(2));
7361 } else {
7362 TmpInst.addOperand(Inst.getOperand(2));
7363 TmpInst.addOperand(Inst.getOperand(1));
7364 }
7365 TmpInst.addOperand(Inst.getOperand(3));
7366 TmpInst.addOperand(Inst.getOperand(4));
7367 Inst = TmpInst;
7368 return true;
7369 }
7370 return false;
7371 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00007372 }
Jim Grosbach83ec8772011-11-10 23:42:14 +00007373 return false;
Jim Grosbachf8fce712011-08-11 17:35:48 +00007374}
7375
Jim Grosbach47a0d522011-08-16 20:45:50 +00007376unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
7377 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
7378 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00007379 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00007380 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00007381 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
7382 assert(MCID.hasOptionalDef() &&
7383 "optionally flag setting instruction missing optional def operand");
7384 assert(MCID.NumOperands == Inst.getNumOperands() &&
7385 "operand count mismatch!");
7386 // Find the optional-def operand (cc_out).
7387 unsigned OpNo;
7388 for (OpNo = 0;
7389 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
7390 ++OpNo)
7391 ;
7392 // If we're parsing Thumb1, reject it completely.
7393 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
7394 return Match_MnemonicFail;
7395 // If we're parsing Thumb2, which form is legal depends on whether we're
7396 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007397 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
7398 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00007399 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007400 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
7401 inITBlock())
7402 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00007403 }
Jim Grosbach194bd892011-08-16 22:20:01 +00007404 // Some high-register supporting Thumb1 encodings only allow both registers
7405 // to be from r0-r7 when in Thumb2.
7406 else if (Opc == ARM::tADDhirr && isThumbOne() &&
7407 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7408 isARMLowRegister(Inst.getOperand(2).getReg()))
7409 return Match_RequiresThumb2;
7410 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00007411 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00007412 isARMLowRegister(Inst.getOperand(0).getReg()) &&
7413 isARMLowRegister(Inst.getOperand(1).getReg()))
7414 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00007415 return Match_Success;
7416}
7417
Jim Grosbach14ce6fa2012-04-24 22:40:08 +00007418static const char *getSubtargetFeatureName(unsigned Val);
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007419bool ARMAsmParser::
7420MatchAndEmitInstruction(SMLoc IDLoc,
7421 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
7422 MCStreamer &Out) {
7423 MCInst Inst;
7424 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00007425 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00007426 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00007427 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00007428 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00007429 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00007430 // Context sensitive operand constraints aren't handled by the matcher,
7431 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00007432 if (validateInstruction(Inst, Operands)) {
7433 // Still progress the IT block, otherwise one wrong condition causes
7434 // nasty cascading errors.
7435 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00007436 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00007437 }
Jim Grosbach189610f2011-07-26 18:25:39 +00007438
Jim Grosbachf8fce712011-08-11 17:35:48 +00007439 // Some instructions need post-processing to, for example, tweak which
Jim Grosbach83ec8772011-11-10 23:42:14 +00007440 // encoding is selected. Loop on it while changes happen so the
7441 // individual transformations can chain off each other. E.g.,
7442 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
7443 while (processInstruction(Inst, Operands))
7444 ;
Jim Grosbachf8fce712011-08-11 17:35:48 +00007445
Jim Grosbacha1109882011-09-02 23:22:08 +00007446 // Only move forward at the very end so that everything in validate
7447 // and process gets a consistent answer about whether we're in an IT
7448 // block.
7449 forwardITPosition();
7450
Jim Grosbach74423e32012-01-25 19:52:01 +00007451 // ITasm is an ARM mode pseudo-instruction that just sets the ITblock and
7452 // doesn't actually encode.
7453 if (Inst.getOpcode() == ARM::ITasm)
7454 return false;
7455
Jim Grosbach42e6bd32012-01-26 23:20:15 +00007456 Inst.setLoc(IDLoc);
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007457 Out.EmitInstruction(Inst);
7458 return false;
Jim Grosbach14ce6fa2012-04-24 22:40:08 +00007459 case Match_MissingFeature: {
7460 assert(ErrorInfo && "Unknown missing feature!");
7461 // Special case the error message for the very common case where only
7462 // a single subtarget feature is missing (Thumb vs. ARM, e.g.).
7463 std::string Msg = "instruction requires:";
7464 unsigned Mask = 1;
7465 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
7466 if (ErrorInfo & Mask) {
7467 Msg += " ";
7468 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
7469 }
7470 Mask <<= 1;
7471 }
7472 return Error(IDLoc, Msg);
7473 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00007474 case Match_InvalidOperand: {
7475 SMLoc ErrorLoc = IDLoc;
7476 if (ErrorInfo != ~0U) {
7477 if (ErrorInfo >= Operands.size())
7478 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00007479
Chris Lattnere73d4f82010-10-28 21:41:58 +00007480 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
7481 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
7482 }
Jim Grosbach16c74252010-10-29 14:46:02 +00007483
Chris Lattnere73d4f82010-10-28 21:41:58 +00007484 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007485 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00007486 case Match_MnemonicFail:
Benjamin Kramer362a05a2012-04-15 17:04:27 +00007487 return Error(IDLoc, "invalid instruction",
7488 ((ARMOperand*)Operands[0])->getLocRange());
Daniel Dunbarb4129152011-02-04 17:12:23 +00007489 case Match_ConversionFail:
Benjamin Kramerd9b0b022012-06-02 10:20:22 +00007490 // The converter function will have already emitted a diagnostic.
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00007491 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007492 case Match_RequiresNotITBlock:
7493 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00007494 case Match_RequiresITBlock:
7495 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00007496 case Match_RequiresV6:
7497 return Error(IDLoc, "instruction variant requires ARMv6 or later");
7498 case Match_RequiresThumb2:
7499 return Error(IDLoc, "instruction variant requires Thumb2");
Jim Grosbach70c9bf32012-06-22 23:56:48 +00007500 case Match_ImmRange0_15: {
7501 SMLoc ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
7502 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
7503 return Error(ErrorLoc, "immediate operand must be in the range [0,15]");
7504 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00007505 }
Jim Grosbach16c74252010-10-29 14:46:02 +00007506
Eric Christopherc223e2b2010-10-29 09:26:59 +00007507 llvm_unreachable("Implement any new match types added!");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007508}
7509
Jim Grosbach1355cf12011-07-26 17:10:22 +00007510/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007511bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
7512 StringRef IDVal = DirectiveID.getIdentifier();
7513 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007514 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007515 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007516 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach9a70df92011-12-07 18:04:19 +00007517 else if (IDVal == ".arm")
7518 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007519 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007520 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007521 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007522 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007523 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007524 return parseDirectiveSyntax(DirectiveID.getLoc());
Jim Grosbacha39cda72011-12-14 02:16:11 +00007525 else if (IDVal == ".unreq")
7526 return parseDirectiveUnreq(DirectiveID.getLoc());
Jason W Kimd7c9e082011-12-20 17:38:12 +00007527 else if (IDVal == ".arch")
7528 return parseDirectiveArch(DirectiveID.getLoc());
7529 else if (IDVal == ".eabi_attribute")
7530 return parseDirectiveEabiAttr(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007531 return true;
7532}
7533
Jim Grosbach1355cf12011-07-26 17:10:22 +00007534/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007535/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00007536bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007537 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7538 for (;;) {
7539 const MCExpr *Value;
7540 if (getParser().ParseExpression(Value))
7541 return true;
7542
Chris Lattneraaec2052010-01-19 19:46:13 +00007543 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007544
7545 if (getLexer().is(AsmToken::EndOfStatement))
7546 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00007547
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007548 // FIXME: Improve diagnostic.
7549 if (getLexer().isNot(AsmToken::Comma))
7550 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007551 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007552 }
7553 }
7554
Sean Callananb9a25b72010-01-19 20:27:46 +00007555 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007556 return false;
7557}
7558
Jim Grosbach1355cf12011-07-26 17:10:22 +00007559/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00007560/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00007561bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00007562 if (getLexer().isNot(AsmToken::EndOfStatement))
7563 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007564 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007565
Jim Grosbach9a70df92011-12-07 18:04:19 +00007566 if (!isThumb())
7567 SwitchMode();
7568 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
7569 return false;
7570}
7571
7572/// parseDirectiveARM
7573/// ::= .arm
7574bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
7575 if (getLexer().isNot(AsmToken::EndOfStatement))
7576 return Error(L, "unexpected token in directive");
7577 Parser.Lex();
7578
7579 if (isThumb())
7580 SwitchMode();
7581 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby515d5092009-10-15 20:48:48 +00007582 return false;
7583}
7584
Jim Grosbach1355cf12011-07-26 17:10:22 +00007585/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00007586/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00007587bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00007588 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
7589 bool isMachO = MAI.hasSubsectionsViaSymbols();
7590 StringRef Name;
Jim Grosbachde4d8392011-12-21 22:30:16 +00007591 bool needFuncName = true;
Rafael Espindola64695402011-05-16 16:17:21 +00007592
Jim Grosbachde4d8392011-12-21 22:30:16 +00007593 // Darwin asm has (optionally) function name after .thumb_func direction
Rafael Espindola64695402011-05-16 16:17:21 +00007594 // ELF doesn't
7595 if (isMachO) {
7596 const AsmToken &Tok = Parser.getTok();
Jim Grosbachde4d8392011-12-21 22:30:16 +00007597 if (Tok.isNot(AsmToken::EndOfStatement)) {
7598 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
7599 return Error(L, "unexpected token in .thumb_func directive");
7600 Name = Tok.getIdentifier();
7601 Parser.Lex(); // Consume the identifier token.
7602 needFuncName = false;
7603 }
Rafael Espindola64695402011-05-16 16:17:21 +00007604 }
7605
Jim Grosbachde4d8392011-12-21 22:30:16 +00007606 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby515d5092009-10-15 20:48:48 +00007607 return Error(L, "unexpected token in directive");
Jim Grosbachde4d8392011-12-21 22:30:16 +00007608
7609 // Eat the end of statement and any blank lines that follow.
7610 while (getLexer().is(AsmToken::EndOfStatement))
7611 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007612
Rafael Espindola64695402011-05-16 16:17:21 +00007613 // FIXME: assuming function name will be the line following .thumb_func
Jim Grosbachde4d8392011-12-21 22:30:16 +00007614 // We really should be checking the next symbol definition even if there's
7615 // stuff in between.
7616 if (needFuncName) {
Jim Grosbachd475f862011-11-10 20:48:53 +00007617 Name = Parser.getTok().getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00007618 }
7619
Jim Grosbach642fc9c2010-11-05 22:33:53 +00007620 // Mark symbol as a thumb symbol.
7621 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
7622 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00007623 return false;
7624}
7625
Jim Grosbach1355cf12011-07-26 17:10:22 +00007626/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00007627/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00007628bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00007629 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00007630 if (Tok.isNot(AsmToken::Identifier))
7631 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00007632 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00007633 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00007634 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00007635 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00007636 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00007637 else
7638 return Error(L, "unrecognized syntax mode in .syntax directive");
7639
7640 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00007641 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007642 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007643
7644 // TODO tell the MC streamer the mode
7645 // getParser().getStreamer().Emit???();
7646 return false;
7647}
7648
Jim Grosbach1355cf12011-07-26 17:10:22 +00007649/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00007650/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00007651bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00007652 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00007653 if (Tok.isNot(AsmToken::Integer))
7654 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00007655 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00007656 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00007657 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00007658 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00007659 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007660 else
7661 return Error(L, "invalid operand to .code directive");
7662
7663 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00007664 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007665 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007666
Evan Cheng32869202011-07-08 22:36:29 +00007667 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00007668 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00007669 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00007670 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00007671 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00007672 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00007673 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00007674 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00007675 }
Jim Grosbach2a301702010-11-05 22:40:53 +00007676
Kevin Enderby515d5092009-10-15 20:48:48 +00007677 return false;
7678}
7679
Jim Grosbacha39cda72011-12-14 02:16:11 +00007680/// parseDirectiveReq
7681/// ::= name .req registername
7682bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
7683 Parser.Lex(); // Eat the '.req' token.
7684 unsigned Reg;
7685 SMLoc SRegLoc, ERegLoc;
7686 if (ParseRegister(Reg, SRegLoc, ERegLoc)) {
7687 Parser.EatToEndOfStatement();
7688 return Error(SRegLoc, "register name expected");
7689 }
7690
7691 // Shouldn't be anything else.
7692 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
7693 Parser.EatToEndOfStatement();
7694 return Error(Parser.getTok().getLoc(),
7695 "unexpected input in .req directive.");
7696 }
7697
7698 Parser.Lex(); // Consume the EndOfStatement
7699
7700 if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg)
7701 return Error(SRegLoc, "redefinition of '" + Name +
7702 "' does not match original.");
7703
7704 return false;
7705}
7706
7707/// parseDirectiveUneq
7708/// ::= .unreq registername
7709bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
7710 if (Parser.getTok().isNot(AsmToken::Identifier)) {
7711 Parser.EatToEndOfStatement();
7712 return Error(L, "unexpected input in .unreq directive.");
7713 }
7714 RegisterReqs.erase(Parser.getTok().getIdentifier());
7715 Parser.Lex(); // Eat the identifier.
7716 return false;
7717}
7718
Jason W Kimd7c9e082011-12-20 17:38:12 +00007719/// parseDirectiveArch
7720/// ::= .arch token
7721bool ARMAsmParser::parseDirectiveArch(SMLoc L) {
7722 return true;
7723}
7724
7725/// parseDirectiveEabiAttr
7726/// ::= .eabi_attribute int, int
7727bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
7728 return true;
7729}
7730
Sean Callanan90b70972010-04-07 20:29:34 +00007731extern "C" void LLVMInitializeARMAsmLexer();
7732
Kevin Enderby9c41fa82009-10-30 22:55:57 +00007733/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007734extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00007735 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
7736 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00007737 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007738}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00007739
Chris Lattner0692ee62010-09-06 19:11:01 +00007740#define GET_REGISTER_MATCHER
Craig Topper8030e1a2012-04-25 06:56:34 +00007741#define GET_SUBTARGET_FEATURE_NAME
Chris Lattner0692ee62010-09-06 19:11:01 +00007742#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00007743#include "ARMGenAsmMatcher.inc"