blob: 2554660eb91ddde1cbc99fce6d7465185d77acd3 [file] [log] [blame]
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00001//===-- ARMAsmParser.cpp - Parse ARM assembly to MCInst instructions ------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Evan Cheng94b95502011-07-26 00:24:13 +000010#include "MCTargetDesc/ARMBaseInfo.h"
Evan Chengee04a6d2011-07-20 23:34:39 +000011#include "MCTargetDesc/ARMAddressingModes.h"
12#include "MCTargetDesc/ARMMCExpr.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000013#include "llvm/MC/MCParser/MCAsmLexer.h"
14#include "llvm/MC/MCParser/MCAsmParser.h"
15#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Rafael Espindola64695402011-05-16 16:17:21 +000016#include "llvm/MC/MCAsmInfo.h"
Jim Grosbach642fc9c2010-11-05 22:33:53 +000017#include "llvm/MC/MCContext.h"
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000018#include "llvm/MC/MCStreamer.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Evan Cheng78011362011-08-23 20:15:21 +000021#include "llvm/MC/MCInstrDesc.h"
Evan Cheng94b95502011-07-26 00:24:13 +000022#include "llvm/MC/MCRegisterInfo.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000023#include "llvm/MC/MCSubtargetInfo.h"
Evan Cheng94b95502011-07-26 00:24:13 +000024#include "llvm/MC/MCTargetAsmParser.h"
Jim Grosbach89df9962011-08-26 21:43:41 +000025#include "llvm/Support/MathExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000026#include "llvm/Support/SourceMgr.h"
Evan Cheng3e74d6f2011-08-24 18:08:43 +000027#include "llvm/Support/TargetRegistry.h"
Daniel Dunbarfa315de2010-08-11 06:37:12 +000028#include "llvm/Support/raw_ostream.h"
Jim Grosbach11e03e72011-08-22 18:50:36 +000029#include "llvm/ADT/BitVector.h"
Benjamin Kramer75ca4b92011-07-08 21:06:23 +000030#include "llvm/ADT/OwningPtr.h"
Evan Cheng94b95502011-07-26 00:24:13 +000031#include "llvm/ADT/STLExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000032#include "llvm/ADT/SmallVector.h"
Daniel Dunbar345a9a62010-08-11 06:37:20 +000033#include "llvm/ADT/StringSwitch.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000034#include "llvm/ADT/Twine.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000035
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000036using namespace llvm;
37
Chris Lattner3a697562010-10-28 17:20:03 +000038namespace {
Bill Wendling146018f2010-11-06 21:42:12 +000039
40class ARMOperand;
Jim Grosbach16c74252010-10-29 14:46:02 +000041
Jim Grosbach7636bf62011-12-02 00:35:16 +000042enum VectorLaneTy { NoLanes, AllLanes, IndexedLane };
Jim Grosbach98b05a52011-11-30 01:09:44 +000043
Evan Cheng94b95502011-07-26 00:24:13 +000044class ARMAsmParser : public MCTargetAsmParser {
Evan Chengffc0e732011-07-09 05:47:46 +000045 MCSubtargetInfo &STI;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000046 MCAsmParser &Parser;
Jim Grosbach28f08c92012-03-05 19:33:30 +000047 const MCRegisterInfo *MRI;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000048
Jim Grosbacha39cda72011-12-14 02:16:11 +000049 // Map of register aliases registers via the .req directive.
50 StringMap<unsigned> RegisterReqs;
51
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000052 struct {
53 ARMCC::CondCodes Cond; // Condition for IT block.
54 unsigned Mask:4; // Condition mask for instructions.
55 // Starting at first 1 (from lsb).
56 // '1' condition as indicated in IT.
57 // '0' inverse of condition (else).
58 // Count of instructions in IT block is
59 // 4 - trailingzeroes(mask)
60
61 bool FirstCond; // Explicit flag for when we're parsing the
62 // First instruction in the IT block. It's
63 // implied in the mask, so needs special
64 // handling.
65
66 unsigned CurPosition; // Current position in parsing of IT
67 // block. In range [0,3]. Initialized
68 // according to count of instructions in block.
69 // ~0U if no active IT block.
70 } ITState;
71 bool inITBlock() { return ITState.CurPosition != ~0U;}
Jim Grosbacha1109882011-09-02 23:22:08 +000072 void forwardITPosition() {
73 if (!inITBlock()) return;
74 // Move to the next instruction in the IT block, if there is one. If not,
75 // mark the block as done.
76 unsigned TZ = CountTrailingZeros_32(ITState.Mask);
77 if (++ITState.CurPosition == 5 - TZ)
78 ITState.CurPosition = ~0U; // Done with the IT block after this.
79 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000080
81
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000082 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000083 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
84
Benjamin Kramer362a05a2012-04-15 17:04:27 +000085 bool Warning(SMLoc L, const Twine &Msg,
86 ArrayRef<SMRange> Ranges = ArrayRef<SMRange>()) {
87 return Parser.Warning(L, Msg, Ranges);
88 }
89 bool Error(SMLoc L, const Twine &Msg,
90 ArrayRef<SMRange> Ranges = ArrayRef<SMRange>()) {
91 return Parser.Error(L, Msg, Ranges);
92 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000093
Jim Grosbach1355cf12011-07-26 17:10:22 +000094 int tryParseRegister();
95 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d87ec22011-07-26 20:41:24 +000096 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000097 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +000098 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000099 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
100 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000101 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
102 unsigned &ShiftAmount);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000103 bool parseDirectiveWord(unsigned Size, SMLoc L);
104 bool parseDirectiveThumb(SMLoc L);
Jim Grosbach9a70df92011-12-07 18:04:19 +0000105 bool parseDirectiveARM(SMLoc L);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000106 bool parseDirectiveThumbFunc(SMLoc L);
107 bool parseDirectiveCode(SMLoc L);
108 bool parseDirectiveSyntax(SMLoc L);
Jim Grosbacha39cda72011-12-14 02:16:11 +0000109 bool parseDirectiveReq(StringRef Name, SMLoc L);
110 bool parseDirectiveUnreq(SMLoc L);
Jason W Kimd7c9e082011-12-20 17:38:12 +0000111 bool parseDirectiveArch(SMLoc L);
112 bool parseDirectiveEabiAttr(SMLoc L);
Kevin Enderby515d5092009-10-15 20:48:48 +0000113
Jim Grosbach1355cf12011-07-26 17:10:22 +0000114 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach89df9962011-08-26 21:43:41 +0000115 bool &CarrySetting, unsigned &ProcessorIMod,
116 StringRef &ITMask);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000117 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +0000118 bool &CanAcceptPredicationCode);
Jim Grosbach16c74252010-10-29 14:46:02 +0000119
Evan Chengebdeeab2011-07-08 01:53:10 +0000120 bool isThumb() const {
121 // FIXME: Can tablegen auto-generate this?
Evan Chengffc0e732011-07-09 05:47:46 +0000122 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000123 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000124 bool isThumbOne() const {
Evan Chengffc0e732011-07-09 05:47:46 +0000125 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000126 }
Jim Grosbach47a0d522011-08-16 20:45:50 +0000127 bool isThumbTwo() const {
128 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
129 }
Jim Grosbach194bd892011-08-16 22:20:01 +0000130 bool hasV6Ops() const {
131 return STI.getFeatureBits() & ARM::HasV6Ops;
132 }
James Molloyacad68d2011-09-28 14:21:38 +0000133 bool hasV7Ops() const {
134 return STI.getFeatureBits() & ARM::HasV7Ops;
135 }
Evan Cheng32869202011-07-08 22:36:29 +0000136 void SwitchMode() {
Evan Chengffc0e732011-07-09 05:47:46 +0000137 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
138 setAvailableFeatures(FB);
Evan Cheng32869202011-07-08 22:36:29 +0000139 }
James Molloyacad68d2011-09-28 14:21:38 +0000140 bool isMClass() const {
141 return STI.getFeatureBits() & ARM::FeatureMClass;
142 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000143
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000144 /// @name Auto-generated Match Functions
145 /// {
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000146
Chris Lattner0692ee62010-09-06 19:11:01 +0000147#define GET_ASSEMBLER_HEADER
148#include "ARMGenAsmMatcher.inc"
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000149
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000150 /// }
151
Jim Grosbach89df9962011-08-26 21:43:41 +0000152 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000153 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000154 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000155 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000156 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000157 OperandMatchResultTy parseCoprocOptionOperand(
158 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000159 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000160 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000161 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000162 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000163 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000164 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachf6c05252011-07-21 17:23:04 +0000165 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
166 StringRef Op, int Low, int High);
167 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
168 return parsePKHImm(O, "lsl", 0, 31);
169 }
170 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
171 return parsePKHImm(O, "asr", 1, 32);
172 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000173 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach580f4a92011-07-25 22:20:28 +0000174 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000175 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000176 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000177 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach251bf252011-08-10 21:56:18 +0000178 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9d390362011-10-03 23:38:36 +0000179 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach862019c2011-10-18 23:02:30 +0000180 OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7636bf62011-12-02 00:35:16 +0000181 OperandMatchResultTy parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000182
183 // Asm Match Converter Methods
Jim Grosbacha77295d2011-09-08 22:07:06 +0000184 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
185 const SmallVectorImpl<MCParsedAsmOperand*> &);
186 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
187 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheeec0252011-09-08 00:39:19 +0000188 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
189 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachee2c2a42011-09-16 21:55:56 +0000190 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
191 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000192 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000193 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson9ab0f252011-08-26 20:43:14 +0000194 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
195 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach548340c2011-08-11 19:22:40 +0000196 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
197 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000198 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000199 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7b8f46c2011-08-11 21:17:22 +0000200 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
201 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000202 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
203 const SmallVectorImpl<MCParsedAsmOperand*> &);
204 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
205 const SmallVectorImpl<MCParsedAsmOperand*> &);
206 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
207 const SmallVectorImpl<MCParsedAsmOperand*> &);
208 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
209 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000210 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
211 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach14605d12011-08-11 20:28:23 +0000212 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
213 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach623a4542011-08-10 22:42:16 +0000214 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
215 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach88ae2bc2011-08-19 22:07:46 +0000216 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
217 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach12431322011-10-24 22:16:58 +0000218 bool cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
219 const SmallVectorImpl<MCParsedAsmOperand*> &);
220 bool cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
221 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach4334e032011-10-31 21:50:31 +0000222 bool cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
223 const SmallVectorImpl<MCParsedAsmOperand*> &);
224 bool cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
225 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach189610f2011-07-26 18:25:39 +0000226
227 bool validateInstruction(MCInst &Inst,
228 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach83ec8772011-11-10 23:42:14 +0000229 bool processInstruction(MCInst &Inst,
Jim Grosbachf8fce712011-08-11 17:35:48 +0000230 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachd54b4e62011-08-16 21:12:37 +0000231 bool shouldOmitCCOutOperand(StringRef Mnemonic,
232 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach189610f2011-07-26 18:25:39 +0000233
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000234public:
Jim Grosbach47a0d522011-08-16 20:45:50 +0000235 enum ARMMatchResultTy {
Jim Grosbach194bd892011-08-16 22:20:01 +0000236 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000237 Match_RequiresNotITBlock,
Jim Grosbach194bd892011-08-16 22:20:01 +0000238 Match_RequiresV6,
239 Match_RequiresThumb2
Jim Grosbach47a0d522011-08-16 20:45:50 +0000240 };
241
Evan Chengffc0e732011-07-09 05:47:46 +0000242 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng94b95502011-07-26 00:24:13 +0000243 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Chengebdeeab2011-07-08 01:53:10 +0000244 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng32869202011-07-08 22:36:29 +0000245
Jim Grosbach28f08c92012-03-05 19:33:30 +0000246 // Cache the MCRegisterInfo.
247 MRI = &getContext().getRegisterInfo();
248
Evan Chengebdeeab2011-07-08 01:53:10 +0000249 // Initialize the set of available features.
Evan Chengffc0e732011-07-09 05:47:46 +0000250 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000251
252 // Not in an ITBlock to start with.
253 ITState.CurPosition = ~0U;
Evan Chengebdeeab2011-07-08 01:53:10 +0000254 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000255
Jim Grosbach1355cf12011-07-26 17:10:22 +0000256 // Implementation of the MCTargetAsmParser interface:
257 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
258 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbach189610f2011-07-26 18:25:39 +0000259 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000260 bool ParseDirective(AsmToken DirectiveID);
261
Jim Grosbach47a0d522011-08-16 20:45:50 +0000262 unsigned checkTargetMatchPredicate(MCInst &Inst);
263
Jim Grosbach1355cf12011-07-26 17:10:22 +0000264 bool MatchAndEmitInstruction(SMLoc IDLoc,
265 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
266 MCStreamer &Out);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000267};
Jim Grosbach16c74252010-10-29 14:46:02 +0000268} // end anonymous namespace
269
Chris Lattner3a697562010-10-28 17:20:03 +0000270namespace {
271
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000272/// ARMOperand - Instances of this class represent a parsed ARM machine
273/// instruction.
Bill Wendling146018f2010-11-06 21:42:12 +0000274class ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000275 enum KindTy {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000276 k_CondCode,
277 k_CCOut,
278 k_ITCondMask,
279 k_CoprocNum,
280 k_CoprocReg,
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000281 k_CoprocOption,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000282 k_Immediate,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000283 k_MemBarrierOpt,
284 k_Memory,
285 k_PostIndexRegister,
286 k_MSRMask,
287 k_ProcIFlags,
Jim Grosbach460a9052011-10-07 23:56:00 +0000288 k_VectorIndex,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000289 k_Register,
290 k_RegisterList,
291 k_DPRRegisterList,
292 k_SPRRegisterList,
Jim Grosbach862019c2011-10-18 23:02:30 +0000293 k_VectorList,
Jim Grosbach98b05a52011-11-30 01:09:44 +0000294 k_VectorListAllLanes,
Jim Grosbach7636bf62011-12-02 00:35:16 +0000295 k_VectorListIndexed,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000296 k_ShiftedRegister,
297 k_ShiftedImmediate,
298 k_ShifterImmediate,
299 k_RotateImmediate,
300 k_BitfieldDescriptor,
301 k_Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000302 } Kind;
303
Sean Callanan76264762010-04-02 22:27:05 +0000304 SMLoc StartLoc, EndLoc;
Bill Wendling24d22d22010-11-18 21:50:54 +0000305 SmallVector<unsigned, 8> Registers;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000306
307 union {
308 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000309 ARMCC::CondCodes Val;
310 } CC;
311
312 struct {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000313 unsigned Val;
314 } Cop;
315
316 struct {
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000317 unsigned Val;
318 } CoprocOption;
319
320 struct {
Jim Grosbach89df9962011-08-26 21:43:41 +0000321 unsigned Mask:4;
322 } ITMask;
323
324 struct {
325 ARM_MB::MemBOpt Val;
326 } MBOpt;
327
328 struct {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000329 ARM_PROC::IFlags Val;
330 } IFlags;
331
332 struct {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000333 unsigned Val;
334 } MMask;
335
336 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000337 const char *Data;
338 unsigned Length;
339 } Tok;
340
341 struct {
342 unsigned RegNum;
343 } Reg;
344
Jim Grosbach862019c2011-10-18 23:02:30 +0000345 // A vector register list is a sequential list of 1 to 4 registers.
346 struct {
347 unsigned RegNum;
348 unsigned Count;
Jim Grosbach7636bf62011-12-02 00:35:16 +0000349 unsigned LaneIndex;
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +0000350 bool isDoubleSpaced;
Jim Grosbach862019c2011-10-18 23:02:30 +0000351 } VectorList;
352
Bill Wendling8155e5b2010-11-06 22:19:43 +0000353 struct {
Jim Grosbach460a9052011-10-07 23:56:00 +0000354 unsigned Val;
355 } VectorIndex;
356
357 struct {
Kevin Enderbycfe07242009-10-13 22:19:02 +0000358 const MCExpr *Val;
359 } Imm;
Jim Grosbach16c74252010-10-29 14:46:02 +0000360
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +0000361 /// Combined record for all forms of ARM address expressions.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000362 struct {
363 unsigned BaseRegNum;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000364 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
365 // was specified.
366 const MCConstantExpr *OffsetImm; // Offset immediate value
367 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
368 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbach57dcb852011-10-11 17:29:55 +0000369 unsigned ShiftImm; // shift for OffsetReg.
370 unsigned Alignment; // 0 = no alignment specified
Jim Grosbacheeaf1c12011-12-19 18:31:43 +0000371 // n = alignment in bytes (2, 4, 8, 16, or 32)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000372 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbache53c87b2011-10-11 15:59:20 +0000373 } Memory;
Owen Anderson00828302011-03-18 22:50:18 +0000374
375 struct {
Jim Grosbach7ce05792011-08-03 23:50:40 +0000376 unsigned RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000377 bool isAdd;
378 ARM_AM::ShiftOpc ShiftTy;
379 unsigned ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000380 } PostIdxReg;
381
382 struct {
Jim Grosbach580f4a92011-07-25 22:20:28 +0000383 bool isASR;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000384 unsigned Imm;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000385 } ShifterImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000386 struct {
387 ARM_AM::ShiftOpc ShiftTy;
388 unsigned SrcReg;
389 unsigned ShiftReg;
390 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000391 } RegShiftedReg;
Owen Anderson92a20222011-07-21 18:54:16 +0000392 struct {
393 ARM_AM::ShiftOpc ShiftTy;
394 unsigned SrcReg;
395 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000396 } RegShiftedImm;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000397 struct {
398 unsigned Imm;
399 } RotImm;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000400 struct {
401 unsigned LSB;
402 unsigned Width;
403 } Bitfield;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000404 };
Jim Grosbach16c74252010-10-29 14:46:02 +0000405
Bill Wendling146018f2010-11-06 21:42:12 +0000406 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
407public:
Sean Callanan76264762010-04-02 22:27:05 +0000408 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
409 Kind = o.Kind;
410 StartLoc = o.StartLoc;
411 EndLoc = o.EndLoc;
412 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000413 case k_CondCode:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000414 CC = o.CC;
415 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000416 case k_ITCondMask:
Jim Grosbach89df9962011-08-26 21:43:41 +0000417 ITMask = o.ITMask;
418 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000419 case k_Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000420 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000421 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000422 case k_CCOut:
423 case k_Register:
Sean Callanan76264762010-04-02 22:27:05 +0000424 Reg = o.Reg;
425 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000426 case k_RegisterList:
427 case k_DPRRegisterList:
428 case k_SPRRegisterList:
Bill Wendling24d22d22010-11-18 21:50:54 +0000429 Registers = o.Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000430 break;
Jim Grosbach862019c2011-10-18 23:02:30 +0000431 case k_VectorList:
Jim Grosbach98b05a52011-11-30 01:09:44 +0000432 case k_VectorListAllLanes:
Jim Grosbach7636bf62011-12-02 00:35:16 +0000433 case k_VectorListIndexed:
Jim Grosbach862019c2011-10-18 23:02:30 +0000434 VectorList = o.VectorList;
435 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000436 case k_CoprocNum:
437 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000438 Cop = o.Cop;
439 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000440 case k_CoprocOption:
441 CoprocOption = o.CoprocOption;
442 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000443 case k_Immediate:
Sean Callanan76264762010-04-02 22:27:05 +0000444 Imm = o.Imm;
445 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000446 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000447 MBOpt = o.MBOpt;
448 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000449 case k_Memory:
Jim Grosbache53c87b2011-10-11 15:59:20 +0000450 Memory = o.Memory;
Sean Callanan76264762010-04-02 22:27:05 +0000451 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000452 case k_PostIndexRegister:
Jim Grosbach7ce05792011-08-03 23:50:40 +0000453 PostIdxReg = o.PostIdxReg;
454 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000455 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000456 MMask = o.MMask;
457 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000458 case k_ProcIFlags:
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000459 IFlags = o.IFlags;
Owen Anderson00828302011-03-18 22:50:18 +0000460 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000461 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +0000462 ShifterImm = o.ShifterImm;
Owen Anderson00828302011-03-18 22:50:18 +0000463 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000464 case k_ShiftedRegister:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000465 RegShiftedReg = o.RegShiftedReg;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000466 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000467 case k_ShiftedImmediate:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000468 RegShiftedImm = o.RegShiftedImm;
Owen Anderson92a20222011-07-21 18:54:16 +0000469 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000470 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000471 RotImm = o.RotImm;
472 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000473 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000474 Bitfield = o.Bitfield;
475 break;
Jim Grosbach460a9052011-10-07 23:56:00 +0000476 case k_VectorIndex:
477 VectorIndex = o.VectorIndex;
478 break;
Sean Callanan76264762010-04-02 22:27:05 +0000479 }
480 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000481
Sean Callanan76264762010-04-02 22:27:05 +0000482 /// getStartLoc - Get the location of the first token of this operand.
483 SMLoc getStartLoc() const { return StartLoc; }
484 /// getEndLoc - Get the location of the last token of this operand.
485 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000486
Benjamin Kramer362a05a2012-04-15 17:04:27 +0000487 SMRange getLocRange() const { return SMRange(StartLoc, EndLoc); }
488
Daniel Dunbar8462b302010-08-11 06:36:53 +0000489 ARMCC::CondCodes getCondCode() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000490 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000491 return CC.Val;
492 }
493
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000494 unsigned getCoproc() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000495 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000496 return Cop.Val;
497 }
498
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000499 StringRef getToken() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000500 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000501 return StringRef(Tok.Data, Tok.Length);
502 }
503
504 unsigned getReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000505 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling7729e062010-11-09 22:44:22 +0000506 return Reg.RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000507 }
508
Bill Wendling5fa22a12010-11-09 23:28:44 +0000509 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000510 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
511 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling24d22d22010-11-18 21:50:54 +0000512 return Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000513 }
514
Kevin Enderbycfe07242009-10-13 22:19:02 +0000515 const MCExpr *getImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000516 assert(isImm() && "Invalid access!");
Kevin Enderbycfe07242009-10-13 22:19:02 +0000517 return Imm.Val;
518 }
519
Jim Grosbach460a9052011-10-07 23:56:00 +0000520 unsigned getVectorIndex() const {
521 assert(Kind == k_VectorIndex && "Invalid access!");
522 return VectorIndex.Val;
523 }
524
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000525 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000526 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000527 return MBOpt.Val;
528 }
529
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000530 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000531 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000532 return IFlags.Val;
533 }
534
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000535 unsigned getMSRMask() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000536 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000537 return MMask.Val;
538 }
539
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000540 bool isCoprocNum() const { return Kind == k_CoprocNum; }
541 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000542 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000543 bool isCondCode() const { return Kind == k_CondCode; }
544 bool isCCOut() const { return Kind == k_CCOut; }
545 bool isITMask() const { return Kind == k_ITCondMask; }
546 bool isITCondCode() const { return Kind == k_CondCode; }
547 bool isImm() const { return Kind == k_Immediate; }
Jim Grosbach51222d12012-01-20 18:09:51 +0000548 bool isFPImm() const {
549 if (!isImm()) return false;
550 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
551 if (!CE) return false;
552 int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
553 return Val != -1;
554 }
Jim Grosbach4050bc42011-12-22 22:19:05 +0000555 bool isFBits16() const {
556 if (!isImm()) return false;
557 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
558 if (!CE) return false;
559 int64_t Value = CE->getValue();
560 return Value >= 0 && Value <= 16;
561 }
562 bool isFBits32() const {
563 if (!isImm()) return false;
564 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
565 if (!CE) return false;
566 int64_t Value = CE->getValue();
567 return Value >= 1 && Value <= 32;
568 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000569 bool isImm8s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000570 if (!isImm()) return false;
Jim Grosbacha77295d2011-09-08 22:07:06 +0000571 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
572 if (!CE) return false;
573 int64_t Value = CE->getValue();
574 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
575 }
Jim Grosbach72f39f82011-08-24 21:22:15 +0000576 bool isImm0_1020s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000577 if (!isImm()) return false;
Jim Grosbach72f39f82011-08-24 21:22:15 +0000578 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
579 if (!CE) return false;
580 int64_t Value = CE->getValue();
581 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
582 }
583 bool isImm0_508s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000584 if (!isImm()) return false;
Jim Grosbach72f39f82011-08-24 21:22:15 +0000585 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
586 if (!CE) return false;
587 int64_t Value = CE->getValue();
588 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
589 }
Jim Grosbach4e53fe82012-04-05 20:57:13 +0000590 bool isImm0_508s4Neg() const {
591 if (!isImm()) return false;
592 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
593 if (!CE) return false;
594 int64_t Value = -CE->getValue();
595 // explicitly exclude zero. we want that to use the normal 0_508 version.
596 return ((Value & 3) == 0) && Value > 0 && Value <= 508;
597 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000598 bool isImm0_255() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000599 if (!isImm()) return false;
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000600 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
601 if (!CE) return false;
602 int64_t Value = CE->getValue();
603 return Value >= 0 && Value < 256;
604 }
Jim Grosbach4e53fe82012-04-05 20:57:13 +0000605 bool isImm0_4095() const {
606 if (!isImm()) return false;
607 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
608 if (!CE) return false;
609 int64_t Value = CE->getValue();
610 return Value >= 0 && Value < 4096;
611 }
612 bool isImm0_4095Neg() const {
613 if (!isImm()) return false;
614 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
615 if (!CE) return false;
616 int64_t Value = -CE->getValue();
617 return Value > 0 && Value < 4096;
618 }
Jim Grosbach587f5062011-12-02 23:34:39 +0000619 bool isImm0_1() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000620 if (!isImm()) return false;
Jim Grosbach587f5062011-12-02 23:34:39 +0000621 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
622 if (!CE) return false;
623 int64_t Value = CE->getValue();
624 return Value >= 0 && Value < 2;
625 }
626 bool isImm0_3() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000627 if (!isImm()) return false;
Jim Grosbach587f5062011-12-02 23:34:39 +0000628 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
629 if (!CE) return false;
630 int64_t Value = CE->getValue();
631 return Value >= 0 && Value < 4;
632 }
Jim Grosbach83ab0702011-07-13 22:01:08 +0000633 bool isImm0_7() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000634 if (!isImm()) return false;
Jim Grosbach83ab0702011-07-13 22:01:08 +0000635 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
636 if (!CE) return false;
637 int64_t Value = CE->getValue();
638 return Value >= 0 && Value < 8;
639 }
640 bool isImm0_15() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000641 if (!isImm()) return false;
Jim Grosbach83ab0702011-07-13 22:01:08 +0000642 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
643 if (!CE) return false;
644 int64_t Value = CE->getValue();
645 return Value >= 0 && Value < 16;
646 }
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000647 bool isImm0_31() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000648 if (!isImm()) return false;
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000649 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
650 if (!CE) return false;
651 int64_t Value = CE->getValue();
652 return Value >= 0 && Value < 32;
653 }
Jim Grosbach730fe6c2011-12-08 01:30:04 +0000654 bool isImm0_63() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000655 if (!isImm()) return false;
Jim Grosbach730fe6c2011-12-08 01:30:04 +0000656 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
657 if (!CE) return false;
658 int64_t Value = CE->getValue();
659 return Value >= 0 && Value < 64;
660 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000661 bool isImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000662 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000663 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
664 if (!CE) return false;
665 int64_t Value = CE->getValue();
666 return Value == 8;
667 }
668 bool isImm16() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000669 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000670 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
671 if (!CE) return false;
672 int64_t Value = CE->getValue();
673 return Value == 16;
674 }
675 bool isImm32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000676 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000677 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
678 if (!CE) return false;
679 int64_t Value = CE->getValue();
680 return Value == 32;
681 }
Jim Grosbach6b044c22011-12-08 22:06:06 +0000682 bool isShrImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000683 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000684 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
685 if (!CE) return false;
686 int64_t Value = CE->getValue();
687 return Value > 0 && Value <= 8;
688 }
689 bool isShrImm16() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000690 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000691 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
692 if (!CE) return false;
693 int64_t Value = CE->getValue();
694 return Value > 0 && Value <= 16;
695 }
696 bool isShrImm32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000697 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000698 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
699 if (!CE) return false;
700 int64_t Value = CE->getValue();
701 return Value > 0 && Value <= 32;
702 }
703 bool isShrImm64() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000704 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000705 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
706 if (!CE) return false;
707 int64_t Value = CE->getValue();
708 return Value > 0 && Value <= 64;
709 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000710 bool isImm1_7() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000711 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000712 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
713 if (!CE) return false;
714 int64_t Value = CE->getValue();
715 return Value > 0 && Value < 8;
716 }
717 bool isImm1_15() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000718 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000719 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
720 if (!CE) return false;
721 int64_t Value = CE->getValue();
722 return Value > 0 && Value < 16;
723 }
724 bool isImm1_31() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000725 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000726 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
727 if (!CE) return false;
728 int64_t Value = CE->getValue();
729 return Value > 0 && Value < 32;
730 }
Jim Grosbachf4943352011-07-25 23:09:14 +0000731 bool isImm1_16() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000732 if (!isImm()) return false;
Jim Grosbachf4943352011-07-25 23:09:14 +0000733 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
734 if (!CE) return false;
735 int64_t Value = CE->getValue();
736 return Value > 0 && Value < 17;
737 }
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000738 bool isImm1_32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000739 if (!isImm()) return false;
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000740 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
741 if (!CE) return false;
742 int64_t Value = CE->getValue();
743 return Value > 0 && Value < 33;
744 }
Jim Grosbachee10ff82011-11-10 19:18:01 +0000745 bool isImm0_32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000746 if (!isImm()) return false;
Jim Grosbachee10ff82011-11-10 19:18:01 +0000747 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
748 if (!CE) return false;
749 int64_t Value = CE->getValue();
750 return Value >= 0 && Value < 33;
751 }
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000752 bool isImm0_65535() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000753 if (!isImm()) return false;
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000754 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
755 if (!CE) return false;
756 int64_t Value = CE->getValue();
757 return Value >= 0 && Value < 65536;
758 }
Jim Grosbachffa32252011-07-19 19:13:28 +0000759 bool isImm0_65535Expr() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000760 if (!isImm()) return false;
Jim Grosbachffa32252011-07-19 19:13:28 +0000761 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
762 // If it's not a constant expression, it'll generate a fixup and be
763 // handled later.
764 if (!CE) return true;
765 int64_t Value = CE->getValue();
766 return Value >= 0 && Value < 65536;
767 }
Jim Grosbached838482011-07-26 16:24:27 +0000768 bool isImm24bit() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000769 if (!isImm()) return false;
Jim Grosbached838482011-07-26 16:24:27 +0000770 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
771 if (!CE) return false;
772 int64_t Value = CE->getValue();
773 return Value >= 0 && Value <= 0xffffff;
774 }
Jim Grosbach70939ee2011-08-17 21:51:27 +0000775 bool isImmThumbSR() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000776 if (!isImm()) return false;
Jim Grosbach70939ee2011-08-17 21:51:27 +0000777 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
778 if (!CE) return false;
779 int64_t Value = CE->getValue();
780 return Value > 0 && Value < 33;
781 }
Jim Grosbachf6c05252011-07-21 17:23:04 +0000782 bool isPKHLSLImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000783 if (!isImm()) return false;
Jim Grosbachf6c05252011-07-21 17:23:04 +0000784 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
785 if (!CE) return false;
786 int64_t Value = CE->getValue();
787 return Value >= 0 && Value < 32;
788 }
789 bool isPKHASRImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000790 if (!isImm()) return false;
Jim Grosbachf6c05252011-07-21 17:23:04 +0000791 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
792 if (!CE) return false;
793 int64_t Value = CE->getValue();
794 return Value > 0 && Value <= 32;
795 }
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000796 bool isARMSOImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000797 if (!isImm()) return false;
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000798 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
799 if (!CE) return false;
800 int64_t Value = CE->getValue();
801 return ARM_AM::getSOImmVal(Value) != -1;
802 }
Jim Grosbache70ec842011-10-28 22:50:54 +0000803 bool isARMSOImmNot() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000804 if (!isImm()) return false;
Jim Grosbache70ec842011-10-28 22:50:54 +0000805 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
806 if (!CE) return false;
807 int64_t Value = CE->getValue();
808 return ARM_AM::getSOImmVal(~Value) != -1;
809 }
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000810 bool isARMSOImmNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000811 if (!isImm()) return false;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000812 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
813 if (!CE) return false;
814 int64_t Value = CE->getValue();
Jim Grosbachad353c62012-03-30 19:59:02 +0000815 // Only use this when not representable as a plain so_imm.
816 return ARM_AM::getSOImmVal(Value) == -1 &&
817 ARM_AM::getSOImmVal(-Value) != -1;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000818 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000819 bool isT2SOImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000820 if (!isImm()) return false;
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000821 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
822 if (!CE) return false;
823 int64_t Value = CE->getValue();
824 return ARM_AM::getT2SOImmVal(Value) != -1;
825 }
Jim Grosbach89a63372011-10-28 22:36:30 +0000826 bool isT2SOImmNot() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000827 if (!isImm()) return false;
Jim Grosbach89a63372011-10-28 22:36:30 +0000828 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
829 if (!CE) return false;
830 int64_t Value = CE->getValue();
831 return ARM_AM::getT2SOImmVal(~Value) != -1;
832 }
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000833 bool isT2SOImmNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000834 if (!isImm()) return false;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000835 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
836 if (!CE) return false;
837 int64_t Value = CE->getValue();
Jim Grosbachad353c62012-03-30 19:59:02 +0000838 // Only use this when not representable as a plain so_imm.
839 return ARM_AM::getT2SOImmVal(Value) == -1 &&
840 ARM_AM::getT2SOImmVal(-Value) != -1;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000841 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000842 bool isSetEndImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000843 if (!isImm()) return false;
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000844 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
845 if (!CE) return false;
846 int64_t Value = CE->getValue();
847 return Value == 1 || Value == 0;
848 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000849 bool isReg() const { return Kind == k_Register; }
850 bool isRegList() const { return Kind == k_RegisterList; }
851 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
852 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
853 bool isToken() const { return Kind == k_Token; }
854 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
855 bool isMemory() const { return Kind == k_Memory; }
856 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
857 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
858 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
859 bool isRotImm() const { return Kind == k_RotateImmediate; }
860 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
861 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000862 bool isPostIdxReg() const {
Jim Grosbach430052b2011-11-14 17:52:47 +0000863 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000864 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000865 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000866 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000867 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000868 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000869 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
870 (alignOK || Memory.Alignment == 0);
871 }
Jim Grosbach0b4c6732012-01-18 22:46:46 +0000872 bool isMemPCRelImm12() const {
873 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
874 return false;
875 // Base register must be PC.
876 if (Memory.BaseRegNum != ARM::PC)
877 return false;
878 // Immediate offset in range [-4095, 4095].
879 if (!Memory.OffsetImm) return true;
880 int64_t Val = Memory.OffsetImm->getValue();
881 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
882 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000883 bool isAlignedMemory() const {
884 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000885 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000886 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000887 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000888 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000889 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000890 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000891 if (!Memory.OffsetImm) return true;
892 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000893 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000894 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000895 bool isAM2OffsetImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000896 if (!isImm()) return false;
Jim Grosbach039c2e12011-08-04 23:01:30 +0000897 // Immediate offset in range [-4095, 4095].
898 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
899 if (!CE) return false;
900 int64_t Val = CE->getValue();
901 return Val > -4096 && Val < 4096;
902 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000903 bool isAddrMode3() const {
Jim Grosbach2f196742011-12-19 23:06:24 +0000904 // If we have an immediate that's not a constant, treat it as a label
905 // reference needing a fixup. If it is a constant, it's something else
906 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000907 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach2f196742011-12-19 23:06:24 +0000908 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000909 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000910 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000911 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000912 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000913 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000914 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000915 if (!Memory.OffsetImm) return true;
916 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000917 return Val > -256 && Val < 256;
918 }
919 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000920 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000921 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000922 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000923 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
924 // Immediate offset in range [-255, 255].
925 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
926 if (!CE) return false;
927 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000928 // Special case, #-0 is INT32_MIN.
929 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000930 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000931 bool isAddrMode5() const {
Jim Grosbach681460f2011-11-01 01:24:45 +0000932 // If we have an immediate that's not a constant, treat it as a label
933 // reference needing a fixup. If it is a constant, it's something else
934 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000935 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach681460f2011-11-01 01:24:45 +0000936 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000937 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000938 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000939 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000940 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000941 if (!Memory.OffsetImm) return true;
942 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000943 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbach681460f2011-11-01 01:24:45 +0000944 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000945 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000946 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000947 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000948 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000949 return false;
950 return true;
951 }
952 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000953 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000954 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
955 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000956 return false;
957 return true;
958 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000959 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000960 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000961 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000962 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000963 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000964 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000965 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
966 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000967 return false;
968 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000969 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000970 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000971 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000972 return false;
973 return true;
974 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000975 bool isMemThumbRR() const {
976 // Thumb reg+reg addressing is simple. Just two registers, a base and
977 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000978 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000979 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000980 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000981 return isARMLowRegister(Memory.BaseRegNum) &&
982 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000983 }
984 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000985 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000986 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000987 return false;
988 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000989 if (!Memory.OffsetImm) return true;
990 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000991 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
992 }
Jim Grosbach38466302011-08-19 18:55:51 +0000993 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000994 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000995 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000996 return false;
997 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000998 if (!Memory.OffsetImm) return true;
999 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +00001000 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
1001 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001002 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +00001003 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +00001004 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001005 return false;
1006 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001007 if (!Memory.OffsetImm) return true;
1008 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001009 return Val >= 0 && Val <= 31;
1010 }
Jim Grosbachecd85892011-08-19 18:13:48 +00001011 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001012 if (!isMemory() || Memory.OffsetRegNum != 0 ||
1013 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +00001014 return false;
1015 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001016 if (!Memory.OffsetImm) return true;
1017 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +00001018 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001019 }
Jim Grosbacha77295d2011-09-08 22:07:06 +00001020 bool isMemImm8s4Offset() const {
Jim Grosbach2f196742011-12-19 23:06:24 +00001021 // If we have an immediate that's not a constant, treat it as a label
1022 // reference needing a fixup. If it is a constant, it's something else
1023 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001024 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach2f196742011-12-19 23:06:24 +00001025 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +00001026 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +00001027 return false;
1028 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001029 if (!Memory.OffsetImm) return true;
1030 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +00001031 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
1032 }
Jim Grosbachb6aed502011-09-09 18:37:27 +00001033 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001034 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +00001035 return false;
1036 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001037 if (!Memory.OffsetImm) return true;
1038 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +00001039 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
1040 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001041 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001042 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001043 return false;
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001044 // Base reg of PC isn't allowed for these encodings.
1045 if (Memory.BaseRegNum == ARM::PC) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001046 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001047 if (!Memory.OffsetImm) return true;
1048 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +00001049 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001050 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001051 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001052 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001053 return false;
1054 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001055 if (!Memory.OffsetImm) return true;
1056 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001057 return Val >= 0 && Val < 256;
1058 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001059 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001060 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001061 return false;
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001062 // Base reg of PC isn't allowed for these encodings.
1063 if (Memory.BaseRegNum == ARM::PC) return false;
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001064 // Immediate offset in range [-255, -1].
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001065 if (!Memory.OffsetImm) return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001066 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001067 return (Val == INT32_MIN) || (Val > -256 && Val < 0);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001068 }
1069 bool isMemUImm12Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001070 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001071 return false;
1072 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001073 if (!Memory.OffsetImm) return true;
1074 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001075 return (Val >= 0 && Val < 4096);
1076 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001077 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +00001078 // If we have an immediate that's not a constant, treat it as a label
1079 // reference needing a fixup. If it is a constant, it's something else
1080 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001081 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +00001082 return true;
1083
Jim Grosbach57dcb852011-10-11 17:29:55 +00001084 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001085 return false;
1086 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001087 if (!Memory.OffsetImm) return true;
1088 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +00001089 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001090 }
1091 bool isPostIdxImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001092 if (!isImm()) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001093 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1094 if (!CE) return false;
1095 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +00001096 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001097 }
Jim Grosbach2bd01182011-10-11 21:55:36 +00001098 bool isPostIdxImm8s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001099 if (!isImm()) return false;
Jim Grosbach2bd01182011-10-11 21:55:36 +00001100 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1101 if (!CE) return false;
1102 int64_t Val = CE->getValue();
1103 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1104 (Val == INT32_MIN);
1105 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001106
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001107 bool isMSRMask() const { return Kind == k_MSRMask; }
1108 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001109
Jim Grosbach0e387b22011-10-17 22:26:03 +00001110 // NEON operands.
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001111 bool isSingleSpacedVectorList() const {
1112 return Kind == k_VectorList && !VectorList.isDoubleSpaced;
1113 }
1114 bool isDoubleSpacedVectorList() const {
1115 return Kind == k_VectorList && VectorList.isDoubleSpaced;
1116 }
Jim Grosbach862019c2011-10-18 23:02:30 +00001117 bool isVecListOneD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001118 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach862019c2011-10-18 23:02:30 +00001119 return VectorList.Count == 1;
1120 }
1121
Jim Grosbach28f08c92012-03-05 19:33:30 +00001122 bool isVecListDPair() const {
1123 if (!isSingleSpacedVectorList()) return false;
1124 return (ARMMCRegisterClasses[ARM::DPairRegClassID]
1125 .contains(VectorList.RegNum));
1126 }
1127
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001128 bool isVecListThreeD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001129 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001130 return VectorList.Count == 3;
1131 }
1132
Jim Grosbachb6310312011-10-21 20:35:01 +00001133 bool isVecListFourD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001134 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachb6310312011-10-21 20:35:01 +00001135 return VectorList.Count == 4;
1136 }
1137
Jim Grosbachc3384c92012-03-05 21:43:40 +00001138 bool isVecListDPairSpaced() const {
Kevin Enderby9f2e1602012-03-20 17:41:51 +00001139 if (isSingleSpacedVectorList()) return false;
Jim Grosbachc3384c92012-03-05 21:43:40 +00001140 return (ARMMCRegisterClasses[ARM::DPairSpcRegClassID]
1141 .contains(VectorList.RegNum));
1142 }
1143
Jim Grosbachc387fc62012-01-23 23:20:46 +00001144 bool isVecListThreeQ() const {
1145 if (!isDoubleSpacedVectorList()) return false;
1146 return VectorList.Count == 3;
1147 }
1148
Jim Grosbach7945ead2012-01-24 00:43:12 +00001149 bool isVecListFourQ() const {
1150 if (!isDoubleSpacedVectorList()) return false;
1151 return VectorList.Count == 4;
1152 }
1153
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001154 bool isSingleSpacedVectorAllLanes() const {
1155 return Kind == k_VectorListAllLanes && !VectorList.isDoubleSpaced;
1156 }
1157 bool isDoubleSpacedVectorAllLanes() const {
1158 return Kind == k_VectorListAllLanes && VectorList.isDoubleSpaced;
1159 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00001160 bool isVecListOneDAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001161 if (!isSingleSpacedVectorAllLanes()) return false;
Jim Grosbach98b05a52011-11-30 01:09:44 +00001162 return VectorList.Count == 1;
1163 }
1164
Jim Grosbachc0fc4502012-03-06 22:01:44 +00001165 bool isVecListDPairAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001166 if (!isSingleSpacedVectorAllLanes()) return false;
Jim Grosbachc0fc4502012-03-06 22:01:44 +00001167 return (ARMMCRegisterClasses[ARM::DPairRegClassID]
1168 .contains(VectorList.RegNum));
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001169 }
1170
Jim Grosbach4d0983a2012-03-06 23:10:38 +00001171 bool isVecListDPairSpacedAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001172 if (!isDoubleSpacedVectorAllLanes()) return false;
Jim Grosbach13af2222011-11-30 18:21:25 +00001173 return VectorList.Count == 2;
1174 }
1175
Jim Grosbach5e59f7e2012-01-24 23:47:04 +00001176 bool isVecListThreeDAllLanes() const {
1177 if (!isSingleSpacedVectorAllLanes()) return false;
1178 return VectorList.Count == 3;
1179 }
1180
1181 bool isVecListThreeQAllLanes() const {
1182 if (!isDoubleSpacedVectorAllLanes()) return false;
1183 return VectorList.Count == 3;
1184 }
1185
Jim Grosbacha57a36a2012-01-25 00:01:08 +00001186 bool isVecListFourDAllLanes() const {
1187 if (!isSingleSpacedVectorAllLanes()) return false;
1188 return VectorList.Count == 4;
1189 }
1190
1191 bool isVecListFourQAllLanes() const {
1192 if (!isDoubleSpacedVectorAllLanes()) return false;
1193 return VectorList.Count == 4;
1194 }
1195
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001196 bool isSingleSpacedVectorIndexed() const {
1197 return Kind == k_VectorListIndexed && !VectorList.isDoubleSpaced;
1198 }
1199 bool isDoubleSpacedVectorIndexed() const {
1200 return Kind == k_VectorListIndexed && VectorList.isDoubleSpaced;
1201 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00001202 bool isVecListOneDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001203 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach7636bf62011-12-02 00:35:16 +00001204 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1205 }
1206
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001207 bool isVecListOneDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001208 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001209 return VectorList.Count == 1 && VectorList.LaneIndex <= 3;
1210 }
1211
1212 bool isVecListOneDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001213 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001214 return VectorList.Count == 1 && VectorList.LaneIndex <= 1;
1215 }
1216
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001217 bool isVecListTwoDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001218 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001219 return VectorList.Count == 2 && VectorList.LaneIndex <= 7;
1220 }
1221
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001222 bool isVecListTwoDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001223 if (!isSingleSpacedVectorIndexed()) return false;
1224 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1225 }
1226
1227 bool isVecListTwoQWordIndexed() const {
1228 if (!isDoubleSpacedVectorIndexed()) return false;
1229 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1230 }
1231
1232 bool isVecListTwoQHWordIndexed() const {
1233 if (!isDoubleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001234 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1235 }
1236
1237 bool isVecListTwoDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001238 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001239 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1240 }
1241
Jim Grosbach3a678af2012-01-23 21:53:26 +00001242 bool isVecListThreeDByteIndexed() const {
1243 if (!isSingleSpacedVectorIndexed()) return false;
1244 return VectorList.Count == 3 && VectorList.LaneIndex <= 7;
1245 }
1246
1247 bool isVecListThreeDHWordIndexed() const {
1248 if (!isSingleSpacedVectorIndexed()) return false;
1249 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1250 }
1251
1252 bool isVecListThreeQWordIndexed() const {
1253 if (!isDoubleSpacedVectorIndexed()) return false;
1254 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1255 }
1256
1257 bool isVecListThreeQHWordIndexed() const {
1258 if (!isDoubleSpacedVectorIndexed()) return false;
1259 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1260 }
1261
1262 bool isVecListThreeDWordIndexed() const {
1263 if (!isSingleSpacedVectorIndexed()) return false;
1264 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1265 }
1266
Jim Grosbache983a132012-01-24 18:37:25 +00001267 bool isVecListFourDByteIndexed() const {
1268 if (!isSingleSpacedVectorIndexed()) return false;
1269 return VectorList.Count == 4 && VectorList.LaneIndex <= 7;
1270 }
1271
1272 bool isVecListFourDHWordIndexed() const {
1273 if (!isSingleSpacedVectorIndexed()) return false;
1274 return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1275 }
1276
1277 bool isVecListFourQWordIndexed() const {
1278 if (!isDoubleSpacedVectorIndexed()) return false;
1279 return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1280 }
1281
1282 bool isVecListFourQHWordIndexed() const {
1283 if (!isDoubleSpacedVectorIndexed()) return false;
1284 return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1285 }
1286
1287 bool isVecListFourDWordIndexed() const {
1288 if (!isSingleSpacedVectorIndexed()) return false;
1289 return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1290 }
1291
Jim Grosbach460a9052011-10-07 23:56:00 +00001292 bool isVectorIndex8() const {
1293 if (Kind != k_VectorIndex) return false;
1294 return VectorIndex.Val < 8;
1295 }
1296 bool isVectorIndex16() const {
1297 if (Kind != k_VectorIndex) return false;
1298 return VectorIndex.Val < 4;
1299 }
1300 bool isVectorIndex32() const {
1301 if (Kind != k_VectorIndex) return false;
1302 return VectorIndex.Val < 2;
1303 }
1304
Jim Grosbach0e387b22011-10-17 22:26:03 +00001305 bool isNEONi8splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001306 if (!isImm()) return false;
Jim Grosbach0e387b22011-10-17 22:26:03 +00001307 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1308 // Must be a constant.
1309 if (!CE) return false;
1310 int64_t Value = CE->getValue();
1311 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1312 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +00001313 return Value >= 0 && Value < 256;
1314 }
Jim Grosbach460a9052011-10-07 23:56:00 +00001315
Jim Grosbachea461102011-10-17 23:09:09 +00001316 bool isNEONi16splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001317 if (!isImm()) return false;
Jim Grosbachea461102011-10-17 23:09:09 +00001318 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1319 // Must be a constant.
1320 if (!CE) return false;
1321 int64_t Value = CE->getValue();
1322 // i16 value in the range [0,255] or [0x0100, 0xff00]
1323 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1324 }
1325
Jim Grosbach6248a542011-10-18 00:22:00 +00001326 bool isNEONi32splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001327 if (!isImm()) return false;
Jim Grosbach6248a542011-10-18 00:22:00 +00001328 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1329 // Must be a constant.
1330 if (!CE) return false;
1331 int64_t Value = CE->getValue();
1332 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1333 return (Value >= 0 && Value < 256) ||
1334 (Value >= 0x0100 && Value <= 0xff00) ||
1335 (Value >= 0x010000 && Value <= 0xff0000) ||
1336 (Value >= 0x01000000 && Value <= 0xff000000);
1337 }
1338
1339 bool isNEONi32vmov() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001340 if (!isImm()) return false;
Jim Grosbach6248a542011-10-18 00:22:00 +00001341 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1342 // Must be a constant.
1343 if (!CE) return false;
1344 int64_t Value = CE->getValue();
1345 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1346 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1347 return (Value >= 0 && Value < 256) ||
1348 (Value >= 0x0100 && Value <= 0xff00) ||
1349 (Value >= 0x010000 && Value <= 0xff0000) ||
1350 (Value >= 0x01000000 && Value <= 0xff000000) ||
1351 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1352 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1353 }
Jim Grosbach9b087852011-12-19 23:51:07 +00001354 bool isNEONi32vmovNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001355 if (!isImm()) return false;
Jim Grosbach9b087852011-12-19 23:51:07 +00001356 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1357 // Must be a constant.
1358 if (!CE) return false;
1359 int64_t Value = ~CE->getValue();
1360 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1361 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1362 return (Value >= 0 && Value < 256) ||
1363 (Value >= 0x0100 && Value <= 0xff00) ||
1364 (Value >= 0x010000 && Value <= 0xff0000) ||
1365 (Value >= 0x01000000 && Value <= 0xff000000) ||
1366 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1367 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1368 }
Jim Grosbach6248a542011-10-18 00:22:00 +00001369
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001370 bool isNEONi64splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001371 if (!isImm()) return false;
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001372 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1373 // Must be a constant.
1374 if (!CE) return false;
1375 uint64_t Value = CE->getValue();
1376 // i64 value with each byte being either 0 or 0xff.
1377 for (unsigned i = 0; i < 8; ++i)
1378 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1379 return true;
1380 }
1381
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001382 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001383 // Add as immediates when possible. Null MCExpr = 0.
1384 if (Expr == 0)
1385 Inst.addOperand(MCOperand::CreateImm(0));
1386 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001387 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1388 else
1389 Inst.addOperand(MCOperand::CreateExpr(Expr));
1390 }
1391
Daniel Dunbar8462b302010-08-11 06:36:53 +00001392 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001393 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001394 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001395 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1396 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001397 }
1398
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001399 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1400 assert(N == 1 && "Invalid number of operands!");
1401 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1402 }
1403
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001404 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1405 assert(N == 1 && "Invalid number of operands!");
1406 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1407 }
1408
1409 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1410 assert(N == 1 && "Invalid number of operands!");
1411 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1412 }
1413
Jim Grosbach89df9962011-08-26 21:43:41 +00001414 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1415 assert(N == 1 && "Invalid number of operands!");
1416 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1417 }
1418
1419 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1420 assert(N == 1 && "Invalid number of operands!");
1421 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1422 }
1423
Jim Grosbachd67641b2010-12-06 18:21:12 +00001424 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1425 assert(N == 1 && "Invalid number of operands!");
1426 Inst.addOperand(MCOperand::CreateReg(getReg()));
1427 }
1428
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001429 void addRegOperands(MCInst &Inst, unsigned N) const {
1430 assert(N == 1 && "Invalid number of operands!");
1431 Inst.addOperand(MCOperand::CreateReg(getReg()));
1432 }
1433
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001434 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001435 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001436 assert(isRegShiftedReg() &&
1437 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001438 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1439 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001440 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001441 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001442 }
1443
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001444 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001445 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001446 assert(isRegShiftedImm() &&
1447 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001448 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001449 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001450 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001451 }
1452
Jim Grosbach580f4a92011-07-25 22:20:28 +00001453 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001454 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001455 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1456 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001457 }
1458
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001459 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001460 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001461 const SmallVectorImpl<unsigned> &RegList = getRegList();
1462 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001463 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1464 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001465 }
1466
Bill Wendling0f630752010-11-17 04:32:08 +00001467 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1468 addRegListOperands(Inst, N);
1469 }
1470
1471 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1472 addRegListOperands(Inst, N);
1473 }
1474
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001475 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1476 assert(N == 1 && "Invalid number of operands!");
1477 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1478 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1479 }
1480
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001481 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1482 assert(N == 1 && "Invalid number of operands!");
1483 // Munge the lsb/width into a bitfield mask.
1484 unsigned lsb = Bitfield.LSB;
1485 unsigned width = Bitfield.Width;
1486 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1487 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1488 (32 - (lsb + width)));
1489 Inst.addOperand(MCOperand::CreateImm(Mask));
1490 }
1491
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001492 void addImmOperands(MCInst &Inst, unsigned N) const {
1493 assert(N == 1 && "Invalid number of operands!");
1494 addExpr(Inst, getImm());
1495 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001496
Jim Grosbach4050bc42011-12-22 22:19:05 +00001497 void addFBits16Operands(MCInst &Inst, unsigned N) const {
1498 assert(N == 1 && "Invalid number of operands!");
1499 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1500 Inst.addOperand(MCOperand::CreateImm(16 - CE->getValue()));
1501 }
1502
1503 void addFBits32Operands(MCInst &Inst, unsigned N) const {
1504 assert(N == 1 && "Invalid number of operands!");
1505 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1506 Inst.addOperand(MCOperand::CreateImm(32 - CE->getValue()));
1507 }
1508
Jim Grosbach9d390362011-10-03 23:38:36 +00001509 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1510 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach51222d12012-01-20 18:09:51 +00001511 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1512 int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
1513 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach9d390362011-10-03 23:38:36 +00001514 }
1515
Jim Grosbacha77295d2011-09-08 22:07:06 +00001516 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1517 assert(N == 1 && "Invalid number of operands!");
1518 // FIXME: We really want to scale the value here, but the LDRD/STRD
1519 // instruction don't encode operands that way yet.
1520 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1521 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1522 }
1523
Jim Grosbach72f39f82011-08-24 21:22:15 +00001524 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1525 assert(N == 1 && "Invalid number of operands!");
1526 // The immediate is scaled by four in the encoding and is stored
1527 // in the MCInst as such. Lop off the low two bits here.
1528 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1529 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1530 }
1531
Jim Grosbach4e53fe82012-04-05 20:57:13 +00001532 void addImm0_508s4NegOperands(MCInst &Inst, unsigned N) const {
1533 assert(N == 1 && "Invalid number of operands!");
1534 // The immediate is scaled by four in the encoding and is stored
1535 // in the MCInst as such. Lop off the low two bits here.
1536 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1537 Inst.addOperand(MCOperand::CreateImm(-(CE->getValue() / 4)));
1538 }
1539
Jim Grosbach72f39f82011-08-24 21:22:15 +00001540 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1541 assert(N == 1 && "Invalid number of operands!");
1542 // The immediate is scaled by four in the encoding and is stored
1543 // in the MCInst as such. Lop off the low two bits here.
1544 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1545 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1546 }
1547
Jim Grosbachf4943352011-07-25 23:09:14 +00001548 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1549 assert(N == 1 && "Invalid number of operands!");
1550 // The constant encodes as the immediate-1, and we store in the instruction
1551 // the bits as encoded, so subtract off one here.
1552 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1553 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1554 }
1555
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001556 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1557 assert(N == 1 && "Invalid number of operands!");
1558 // The constant encodes as the immediate-1, and we store in the instruction
1559 // the bits as encoded, so subtract off one here.
1560 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1561 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1562 }
1563
Jim Grosbach70939ee2011-08-17 21:51:27 +00001564 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1565 assert(N == 1 && "Invalid number of operands!");
1566 // The constant encodes as the immediate, except for 32, which encodes as
1567 // zero.
1568 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1569 unsigned Imm = CE->getValue();
1570 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1571 }
1572
Jim Grosbachf6c05252011-07-21 17:23:04 +00001573 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1574 assert(N == 1 && "Invalid number of operands!");
1575 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1576 // the instruction as well.
1577 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1578 int Val = CE->getValue();
1579 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1580 }
1581
Jim Grosbach89a63372011-10-28 22:36:30 +00001582 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1583 assert(N == 1 && "Invalid number of operands!");
1584 // The operand is actually a t2_so_imm, but we have its bitwise
1585 // negation in the assembly source, so twiddle it here.
1586 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1587 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1588 }
1589
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001590 void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1591 assert(N == 1 && "Invalid number of operands!");
1592 // The operand is actually a t2_so_imm, but we have its
1593 // negation in the assembly source, so twiddle it here.
1594 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1595 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1596 }
1597
Jim Grosbach4e53fe82012-04-05 20:57:13 +00001598 void addImm0_4095NegOperands(MCInst &Inst, unsigned N) const {
1599 assert(N == 1 && "Invalid number of operands!");
1600 // The operand is actually an imm0_4095, but we have its
1601 // negation in the assembly source, so twiddle it here.
1602 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1603 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1604 }
1605
Jim Grosbache70ec842011-10-28 22:50:54 +00001606 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1607 assert(N == 1 && "Invalid number of operands!");
1608 // The operand is actually a so_imm, but we have its bitwise
1609 // negation in the assembly source, so twiddle it here.
1610 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1611 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1612 }
1613
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001614 void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
1615 assert(N == 1 && "Invalid number of operands!");
1616 // The operand is actually a so_imm, but we have its
1617 // negation in the assembly source, so twiddle it here.
1618 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1619 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1620 }
1621
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001622 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1623 assert(N == 1 && "Invalid number of operands!");
1624 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1625 }
1626
Jim Grosbach7ce05792011-08-03 23:50:40 +00001627 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1628 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001629 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001630 }
1631
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001632 void addMemPCRelImm12Operands(MCInst &Inst, unsigned N) const {
1633 assert(N == 1 && "Invalid number of operands!");
1634 int32_t Imm = Memory.OffsetImm->getValue();
1635 // FIXME: Handle #-0
1636 if (Imm == INT32_MIN) Imm = 0;
1637 Inst.addOperand(MCOperand::CreateImm(Imm));
1638 }
1639
Jim Grosbach57dcb852011-10-11 17:29:55 +00001640 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1641 assert(N == 2 && "Invalid number of operands!");
1642 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1643 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1644 }
1645
Jim Grosbach7ce05792011-08-03 23:50:40 +00001646 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1647 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001648 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1649 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001650 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1651 // Special case for #-0
1652 if (Val == INT32_MIN) Val = 0;
1653 if (Val < 0) Val = -Val;
1654 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1655 } else {
1656 // For register offset, we encode the shift type and negation flag
1657 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001658 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1659 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001660 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001661 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1662 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001663 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001664 }
1665
Jim Grosbach039c2e12011-08-04 23:01:30 +00001666 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1667 assert(N == 2 && "Invalid number of operands!");
1668 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1669 assert(CE && "non-constant AM2OffsetImm operand!");
1670 int32_t Val = CE->getValue();
1671 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1672 // Special case for #-0
1673 if (Val == INT32_MIN) Val = 0;
1674 if (Val < 0) Val = -Val;
1675 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1676 Inst.addOperand(MCOperand::CreateReg(0));
1677 Inst.addOperand(MCOperand::CreateImm(Val));
1678 }
1679
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001680 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1681 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001682 // If we have an immediate that's not a constant, treat it as a label
1683 // reference needing a fixup. If it is a constant, it's something else
1684 // and we reject it.
1685 if (isImm()) {
1686 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1687 Inst.addOperand(MCOperand::CreateReg(0));
1688 Inst.addOperand(MCOperand::CreateImm(0));
1689 return;
1690 }
1691
Jim Grosbache53c87b2011-10-11 15:59:20 +00001692 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1693 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001694 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1695 // Special case for #-0
1696 if (Val == INT32_MIN) Val = 0;
1697 if (Val < 0) Val = -Val;
1698 Val = ARM_AM::getAM3Opc(AddSub, Val);
1699 } else {
1700 // For register offset, we encode the shift type and negation flag
1701 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001702 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001703 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001704 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1705 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001706 Inst.addOperand(MCOperand::CreateImm(Val));
1707 }
1708
1709 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1710 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001711 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001712 int32_t Val =
1713 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1714 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1715 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001716 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001717 }
1718
1719 // Constant offset.
1720 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1721 int32_t Val = CE->getValue();
1722 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1723 // Special case for #-0
1724 if (Val == INT32_MIN) Val = 0;
1725 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001726 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001727 Inst.addOperand(MCOperand::CreateReg(0));
1728 Inst.addOperand(MCOperand::CreateImm(Val));
1729 }
1730
Jim Grosbach7ce05792011-08-03 23:50:40 +00001731 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1732 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach681460f2011-11-01 01:24:45 +00001733 // If we have an immediate that's not a constant, treat it as a label
1734 // reference needing a fixup. If it is a constant, it's something else
1735 // and we reject it.
1736 if (isImm()) {
1737 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1738 Inst.addOperand(MCOperand::CreateImm(0));
1739 return;
1740 }
1741
Jim Grosbach7ce05792011-08-03 23:50:40 +00001742 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001743 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001744 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1745 // Special case for #-0
1746 if (Val == INT32_MIN) Val = 0;
1747 if (Val < 0) Val = -Val;
1748 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001749 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001750 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001751 }
1752
Jim Grosbacha77295d2011-09-08 22:07:06 +00001753 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1754 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001755 // If we have an immediate that's not a constant, treat it as a label
1756 // reference needing a fixup. If it is a constant, it's something else
1757 // and we reject it.
1758 if (isImm()) {
1759 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1760 Inst.addOperand(MCOperand::CreateImm(0));
1761 return;
1762 }
1763
Jim Grosbache53c87b2011-10-11 15:59:20 +00001764 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1765 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001766 Inst.addOperand(MCOperand::CreateImm(Val));
1767 }
1768
Jim Grosbachb6aed502011-09-09 18:37:27 +00001769 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1770 assert(N == 2 && "Invalid number of operands!");
1771 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001772 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1773 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001774 Inst.addOperand(MCOperand::CreateImm(Val));
1775 }
1776
Jim Grosbach7ce05792011-08-03 23:50:40 +00001777 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1778 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001779 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1780 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001781 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001782 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001783
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001784 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1785 addMemImm8OffsetOperands(Inst, N);
1786 }
1787
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001788 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001789 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001790 }
1791
1792 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1793 assert(N == 2 && "Invalid number of operands!");
1794 // If this is an immediate, it's a label reference.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001795 if (isImm()) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001796 addExpr(Inst, getImm());
1797 Inst.addOperand(MCOperand::CreateImm(0));
1798 return;
1799 }
1800
1801 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001802 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1803 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001804 Inst.addOperand(MCOperand::CreateImm(Val));
1805 }
1806
Jim Grosbach7ce05792011-08-03 23:50:40 +00001807 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1808 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001809 // If this is an immediate, it's a label reference.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001810 if (isImm()) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001811 addExpr(Inst, getImm());
1812 Inst.addOperand(MCOperand::CreateImm(0));
1813 return;
1814 }
1815
1816 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001817 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1818 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001819 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001820 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001821
Jim Grosbach7f739be2011-09-19 22:21:13 +00001822 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1823 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001824 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1825 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001826 }
1827
1828 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1829 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001830 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1831 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001832 }
1833
Jim Grosbach7ce05792011-08-03 23:50:40 +00001834 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1835 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001836 unsigned Val =
1837 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1838 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001839 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1840 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001841 Inst.addOperand(MCOperand::CreateImm(Val));
1842 }
1843
Jim Grosbachab899c12011-09-07 23:10:15 +00001844 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1845 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001846 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1847 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1848 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001849 }
1850
Jim Grosbach7ce05792011-08-03 23:50:40 +00001851 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1852 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001853 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1854 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001855 }
1856
Jim Grosbach60f91a32011-08-19 17:55:24 +00001857 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1858 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001859 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1860 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001861 Inst.addOperand(MCOperand::CreateImm(Val));
1862 }
1863
Jim Grosbach38466302011-08-19 18:55:51 +00001864 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1865 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001866 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1867 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001868 Inst.addOperand(MCOperand::CreateImm(Val));
1869 }
1870
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001871 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1872 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001873 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1874 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001875 Inst.addOperand(MCOperand::CreateImm(Val));
1876 }
1877
Jim Grosbachecd85892011-08-19 18:13:48 +00001878 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1879 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001880 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1881 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001882 Inst.addOperand(MCOperand::CreateImm(Val));
1883 }
1884
Jim Grosbach7ce05792011-08-03 23:50:40 +00001885 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1886 assert(N == 1 && "Invalid number of operands!");
1887 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1888 assert(CE && "non-constant post-idx-imm8 operand!");
1889 int Imm = CE->getValue();
1890 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001891 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001892 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1893 Inst.addOperand(MCOperand::CreateImm(Imm));
1894 }
1895
Jim Grosbach2bd01182011-10-11 21:55:36 +00001896 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1897 assert(N == 1 && "Invalid number of operands!");
1898 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1899 assert(CE && "non-constant post-idx-imm8s4 operand!");
1900 int Imm = CE->getValue();
1901 bool isAdd = Imm >= 0;
1902 if (Imm == INT32_MIN) Imm = 0;
1903 // Immediate is scaled by 4.
1904 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1905 Inst.addOperand(MCOperand::CreateImm(Imm));
1906 }
1907
Jim Grosbach7ce05792011-08-03 23:50:40 +00001908 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1909 assert(N == 2 && "Invalid number of operands!");
1910 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001911 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1912 }
1913
1914 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1915 assert(N == 2 && "Invalid number of operands!");
1916 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1917 // The sign, shift type, and shift amount are encoded in a single operand
1918 // using the AM2 encoding helpers.
1919 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1920 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1921 PostIdxReg.ShiftTy);
1922 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001923 }
1924
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001925 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1926 assert(N == 1 && "Invalid number of operands!");
1927 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1928 }
1929
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001930 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1931 assert(N == 1 && "Invalid number of operands!");
1932 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1933 }
1934
Jim Grosbach6029b6d2011-11-29 23:51:09 +00001935 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach862019c2011-10-18 23:02:30 +00001936 assert(N == 1 && "Invalid number of operands!");
1937 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1938 }
1939
Jim Grosbach7636bf62011-12-02 00:35:16 +00001940 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1941 assert(N == 2 && "Invalid number of operands!");
1942 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1943 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1944 }
1945
Jim Grosbach460a9052011-10-07 23:56:00 +00001946 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1947 assert(N == 1 && "Invalid number of operands!");
1948 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1949 }
1950
1951 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1952 assert(N == 1 && "Invalid number of operands!");
1953 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1954 }
1955
1956 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1957 assert(N == 1 && "Invalid number of operands!");
1958 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1959 }
1960
Jim Grosbach0e387b22011-10-17 22:26:03 +00001961 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1962 assert(N == 1 && "Invalid number of operands!");
1963 // The immediate encodes the type of constant as well as the value.
1964 // Mask in that this is an i8 splat.
1965 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1966 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1967 }
1968
Jim Grosbachea461102011-10-17 23:09:09 +00001969 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1970 assert(N == 1 && "Invalid number of operands!");
1971 // The immediate encodes the type of constant as well as the value.
1972 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1973 unsigned Value = CE->getValue();
1974 if (Value >= 256)
1975 Value = (Value >> 8) | 0xa00;
1976 else
1977 Value |= 0x800;
1978 Inst.addOperand(MCOperand::CreateImm(Value));
1979 }
1980
Jim Grosbach6248a542011-10-18 00:22:00 +00001981 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1982 assert(N == 1 && "Invalid number of operands!");
1983 // The immediate encodes the type of constant as well as the value.
1984 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1985 unsigned Value = CE->getValue();
1986 if (Value >= 256 && Value <= 0xff00)
1987 Value = (Value >> 8) | 0x200;
1988 else if (Value > 0xffff && Value <= 0xff0000)
1989 Value = (Value >> 16) | 0x400;
1990 else if (Value > 0xffffff)
1991 Value = (Value >> 24) | 0x600;
1992 Inst.addOperand(MCOperand::CreateImm(Value));
1993 }
1994
1995 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1996 assert(N == 1 && "Invalid number of operands!");
1997 // The immediate encodes the type of constant as well as the value.
1998 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1999 unsigned Value = CE->getValue();
2000 if (Value >= 256 && Value <= 0xffff)
2001 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
2002 else if (Value > 0xffff && Value <= 0xffffff)
2003 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
2004 else if (Value > 0xffffff)
2005 Value = (Value >> 24) | 0x600;
2006 Inst.addOperand(MCOperand::CreateImm(Value));
2007 }
2008
Jim Grosbach9b087852011-12-19 23:51:07 +00002009 void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const {
2010 assert(N == 1 && "Invalid number of operands!");
2011 // The immediate encodes the type of constant as well as the value.
2012 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2013 unsigned Value = ~CE->getValue();
2014 if (Value >= 256 && Value <= 0xffff)
2015 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
2016 else if (Value > 0xffff && Value <= 0xffffff)
2017 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
2018 else if (Value > 0xffffff)
2019 Value = (Value >> 24) | 0x600;
2020 Inst.addOperand(MCOperand::CreateImm(Value));
2021 }
2022
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00002023 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
2024 assert(N == 1 && "Invalid number of operands!");
2025 // The immediate encodes the type of constant as well as the value.
2026 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2027 uint64_t Value = CE->getValue();
2028 unsigned Imm = 0;
2029 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
2030 Imm |= (Value & 1) << i;
2031 }
2032 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
2033 }
2034
Jim Grosbachb7f689b2011-07-13 15:34:57 +00002035 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00002036
Jim Grosbach89df9962011-08-26 21:43:41 +00002037 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002038 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00002039 Op->ITMask.Mask = Mask;
2040 Op->StartLoc = S;
2041 Op->EndLoc = S;
2042 return Op;
2043 }
2044
Chris Lattner3a697562010-10-28 17:20:03 +00002045 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002046 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00002047 Op->CC.Val = CC;
2048 Op->StartLoc = S;
2049 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00002050 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00002051 }
2052
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002053 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002054 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002055 Op->Cop.Val = CopVal;
2056 Op->StartLoc = S;
2057 Op->EndLoc = S;
2058 return Op;
2059 }
2060
2061 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002062 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002063 Op->Cop.Val = CopVal;
2064 Op->StartLoc = S;
2065 Op->EndLoc = S;
2066 return Op;
2067 }
2068
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002069 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
2070 ARMOperand *Op = new ARMOperand(k_CoprocOption);
2071 Op->Cop.Val = Val;
2072 Op->StartLoc = S;
2073 Op->EndLoc = E;
2074 return Op;
2075 }
2076
Jim Grosbachd67641b2010-12-06 18:21:12 +00002077 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002078 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00002079 Op->Reg.RegNum = RegNum;
2080 Op->StartLoc = S;
2081 Op->EndLoc = S;
2082 return Op;
2083 }
2084
Chris Lattner3a697562010-10-28 17:20:03 +00002085 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002086 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00002087 Op->Tok.Data = Str.data();
2088 Op->Tok.Length = Str.size();
2089 Op->StartLoc = S;
2090 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00002091 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002092 }
2093
Bill Wendling50d0f582010-11-18 23:43:05 +00002094 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002095 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00002096 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00002097 Op->StartLoc = S;
2098 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002099 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002100 }
2101
Jim Grosbache8606dc2011-07-13 17:50:29 +00002102 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
2103 unsigned SrcReg,
2104 unsigned ShiftReg,
2105 unsigned ShiftImm,
2106 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002107 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002108 Op->RegShiftedReg.ShiftTy = ShTy;
2109 Op->RegShiftedReg.SrcReg = SrcReg;
2110 Op->RegShiftedReg.ShiftReg = ShiftReg;
2111 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002112 Op->StartLoc = S;
2113 Op->EndLoc = E;
2114 return Op;
2115 }
2116
Owen Anderson92a20222011-07-21 18:54:16 +00002117 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
2118 unsigned SrcReg,
2119 unsigned ShiftImm,
2120 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002121 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002122 Op->RegShiftedImm.ShiftTy = ShTy;
2123 Op->RegShiftedImm.SrcReg = SrcReg;
2124 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00002125 Op->StartLoc = S;
2126 Op->EndLoc = E;
2127 return Op;
2128 }
2129
Jim Grosbach580f4a92011-07-25 22:20:28 +00002130 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002131 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002132 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00002133 Op->ShifterImm.isASR = isASR;
2134 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00002135 Op->StartLoc = S;
2136 Op->EndLoc = E;
2137 return Op;
2138 }
2139
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002140 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002141 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002142 Op->RotImm.Imm = Imm;
2143 Op->StartLoc = S;
2144 Op->EndLoc = E;
2145 return Op;
2146 }
2147
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002148 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
2149 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002150 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002151 Op->Bitfield.LSB = LSB;
2152 Op->Bitfield.Width = Width;
2153 Op->StartLoc = S;
2154 Op->EndLoc = E;
2155 return Op;
2156 }
2157
Bill Wendling7729e062010-11-09 22:44:22 +00002158 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00002159 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002160 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002161 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002162
Jim Grosbachd300b942011-09-13 22:56:44 +00002163 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002164 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00002165 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00002166 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002167 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002168
2169 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00002170 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002171 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00002172 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00002173 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002174 Op->StartLoc = StartLoc;
2175 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00002176 return Op;
2177 }
2178
Jim Grosbach862019c2011-10-18 23:02:30 +00002179 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002180 bool isDoubleSpaced, SMLoc S, SMLoc E) {
Jim Grosbach862019c2011-10-18 23:02:30 +00002181 ARMOperand *Op = new ARMOperand(k_VectorList);
2182 Op->VectorList.RegNum = RegNum;
2183 Op->VectorList.Count = Count;
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002184 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach862019c2011-10-18 23:02:30 +00002185 Op->StartLoc = S;
2186 Op->EndLoc = E;
2187 return Op;
2188 }
2189
Jim Grosbach98b05a52011-11-30 01:09:44 +00002190 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002191 bool isDoubleSpaced,
Jim Grosbach98b05a52011-11-30 01:09:44 +00002192 SMLoc S, SMLoc E) {
2193 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
2194 Op->VectorList.RegNum = RegNum;
2195 Op->VectorList.Count = Count;
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002196 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002197 Op->StartLoc = S;
2198 Op->EndLoc = E;
2199 return Op;
2200 }
2201
Jim Grosbach7636bf62011-12-02 00:35:16 +00002202 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002203 unsigned Index,
2204 bool isDoubleSpaced,
2205 SMLoc S, SMLoc E) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002206 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
2207 Op->VectorList.RegNum = RegNum;
2208 Op->VectorList.Count = Count;
2209 Op->VectorList.LaneIndex = Index;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002210 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002211 Op->StartLoc = S;
2212 Op->EndLoc = E;
2213 return Op;
2214 }
2215
Jim Grosbach460a9052011-10-07 23:56:00 +00002216 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
2217 MCContext &Ctx) {
2218 ARMOperand *Op = new ARMOperand(k_VectorIndex);
2219 Op->VectorIndex.Val = Idx;
2220 Op->StartLoc = S;
2221 Op->EndLoc = E;
2222 return Op;
2223 }
2224
Chris Lattner3a697562010-10-28 17:20:03 +00002225 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002226 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00002227 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00002228 Op->StartLoc = S;
2229 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002230 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00002231 }
2232
Jim Grosbach7ce05792011-08-03 23:50:40 +00002233 static ARMOperand *CreateMem(unsigned BaseRegNum,
2234 const MCConstantExpr *OffsetImm,
2235 unsigned OffsetRegNum,
2236 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002237 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00002238 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002239 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00002240 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002241 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00002242 Op->Memory.BaseRegNum = BaseRegNum;
2243 Op->Memory.OffsetImm = OffsetImm;
2244 Op->Memory.OffsetRegNum = OffsetRegNum;
2245 Op->Memory.ShiftType = ShiftType;
2246 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00002247 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00002248 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002249 Op->StartLoc = S;
2250 Op->EndLoc = E;
2251 return Op;
2252 }
Jim Grosbach16c74252010-10-29 14:46:02 +00002253
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002254 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
2255 ARM_AM::ShiftOpc ShiftTy,
2256 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002257 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002258 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002259 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002260 Op->PostIdxReg.isAdd = isAdd;
2261 Op->PostIdxReg.ShiftTy = ShiftTy;
2262 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00002263 Op->StartLoc = S;
2264 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002265 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002266 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002267
2268 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002269 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002270 Op->MBOpt.Val = Opt;
2271 Op->StartLoc = S;
2272 Op->EndLoc = S;
2273 return Op;
2274 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002275
2276 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002277 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002278 Op->IFlags.Val = IFlags;
2279 Op->StartLoc = S;
2280 Op->EndLoc = S;
2281 return Op;
2282 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002283
2284 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002285 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002286 Op->MMask.Val = MMask;
2287 Op->StartLoc = S;
2288 Op->EndLoc = S;
2289 return Op;
2290 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002291};
2292
2293} // end anonymous namespace.
2294
Jim Grosbachb7f689b2011-07-13 15:34:57 +00002295void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002296 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002297 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00002298 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002299 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002300 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00002301 OS << "<ccout " << getReg() << ">";
2302 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002303 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002304 static const char *MaskStr[] = {
2305 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2306 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2307 };
Jim Grosbach89df9962011-08-26 21:43:41 +00002308 assert((ITMask.Mask & 0xf) == ITMask.Mask);
2309 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2310 break;
2311 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002312 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002313 OS << "<coprocessor number: " << getCoproc() << ">";
2314 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002315 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002316 OS << "<coprocessor register: " << getCoproc() << ">";
2317 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002318 case k_CoprocOption:
2319 OS << "<coprocessor option: " << CoprocOption.Val << ">";
2320 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002321 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002322 OS << "<mask: " << getMSRMask() << ">";
2323 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002324 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002325 getImm()->print(OS);
2326 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002327 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002328 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2329 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002330 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002331 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00002332 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002333 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002334 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002335 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002336 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2337 << PostIdxReg.RegNum;
2338 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2339 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2340 << PostIdxReg.ShiftImm;
2341 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00002342 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002343 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002344 OS << "<ARM_PROC::";
2345 unsigned IFlags = getProcIFlags();
2346 for (int i=2; i >= 0; --i)
2347 if (IFlags & (1 << i))
2348 OS << ARM_PROC::IFlagsToString(1 << i);
2349 OS << ">";
2350 break;
2351 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002352 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00002353 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002354 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002355 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00002356 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2357 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00002358 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002359 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00002360 OS << "<so_reg_reg "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002361 << RegShiftedReg.SrcReg << " "
2362 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2363 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson00828302011-03-18 22:50:18 +00002364 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002365 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00002366 OS << "<so_reg_imm "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002367 << RegShiftedImm.SrcReg << " "
2368 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2369 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Anderson92a20222011-07-21 18:54:16 +00002370 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002371 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002372 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2373 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002374 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002375 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2376 << ", width: " << Bitfield.Width << ">";
2377 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002378 case k_RegisterList:
2379 case k_DPRRegisterList:
2380 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00002381 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002382
Bill Wendling5fa22a12010-11-09 23:28:44 +00002383 const SmallVectorImpl<unsigned> &RegList = getRegList();
2384 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002385 I = RegList.begin(), E = RegList.end(); I != E; ) {
2386 OS << *I;
2387 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002388 }
2389
2390 OS << ">";
2391 break;
2392 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002393 case k_VectorList:
2394 OS << "<vector_list " << VectorList.Count << " * "
2395 << VectorList.RegNum << ">";
2396 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002397 case k_VectorListAllLanes:
2398 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2399 << VectorList.RegNum << ">";
2400 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002401 case k_VectorListIndexed:
2402 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2403 << VectorList.Count << " * " << VectorList.RegNum << ">";
2404 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002405 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002406 OS << "'" << getToken() << "'";
2407 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00002408 case k_VectorIndex:
2409 OS << "<vectorindex " << getVectorIndex() << ">";
2410 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002411 }
2412}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00002413
2414/// @name Auto-generated Match Functions
2415/// {
2416
2417static unsigned MatchRegisterName(StringRef Name);
2418
2419/// }
2420
Bob Wilson69df7232011-02-03 21:46:10 +00002421bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2422 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbacha39cda72011-12-14 02:16:11 +00002423 StartLoc = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002424 RegNo = tryParseRegister();
Jim Grosbacha39cda72011-12-14 02:16:11 +00002425 EndLoc = Parser.getTok().getLoc();
Roman Divackybf755322011-01-27 17:14:22 +00002426
2427 return (RegNo == (unsigned)-1);
2428}
2429
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002430/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002431/// and if it is a register name the token is eaten and the register number is
2432/// returned. Otherwise return -1.
2433///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002434int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002435 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002436 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002437
Benjamin Kramer59085362011-11-06 20:37:06 +00002438 std::string lowerCase = Tok.getString().lower();
Owen Anderson0c9f2502011-01-13 22:50:36 +00002439 unsigned RegNum = MatchRegisterName(lowerCase);
2440 if (!RegNum) {
2441 RegNum = StringSwitch<unsigned>(lowerCase)
2442 .Case("r13", ARM::SP)
2443 .Case("r14", ARM::LR)
2444 .Case("r15", ARM::PC)
2445 .Case("ip", ARM::R12)
Jim Grosbach40e28552011-12-08 19:27:38 +00002446 // Additional register name aliases for 'gas' compatibility.
2447 .Case("a1", ARM::R0)
2448 .Case("a2", ARM::R1)
2449 .Case("a3", ARM::R2)
2450 .Case("a4", ARM::R3)
2451 .Case("v1", ARM::R4)
2452 .Case("v2", ARM::R5)
2453 .Case("v3", ARM::R6)
2454 .Case("v4", ARM::R7)
2455 .Case("v5", ARM::R8)
2456 .Case("v6", ARM::R9)
2457 .Case("v7", ARM::R10)
2458 .Case("v8", ARM::R11)
2459 .Case("sb", ARM::R9)
2460 .Case("sl", ARM::R10)
2461 .Case("fp", ARM::R11)
Owen Anderson0c9f2502011-01-13 22:50:36 +00002462 .Default(0);
2463 }
Jim Grosbacha39cda72011-12-14 02:16:11 +00002464 if (!RegNum) {
Jim Grosbachaee718b2011-12-20 23:11:00 +00002465 // Check for aliases registered via .req. Canonicalize to lower case.
2466 // That's more consistent since register names are case insensitive, and
2467 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2468 StringMap<unsigned>::const_iterator Entry = RegisterReqs.find(lowerCase);
Jim Grosbacha39cda72011-12-14 02:16:11 +00002469 // If no match, return failure.
2470 if (Entry == RegisterReqs.end())
2471 return -1;
2472 Parser.Lex(); // Eat identifier token.
2473 return Entry->getValue();
2474 }
Bob Wilson69df7232011-02-03 21:46:10 +00002475
Chris Lattnere5658fa2010-10-30 04:09:10 +00002476 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002477
Chris Lattnere5658fa2010-10-30 04:09:10 +00002478 return RegNum;
2479}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002480
Jim Grosbach19906722011-07-13 18:49:30 +00002481// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2482// If a recoverable error occurs, return 1. If an irrecoverable error
2483// occurs, return -1. An irrecoverable error is one where tokens have been
2484// consumed in the process of trying to parse the shifter (i.e., when it is
2485// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002486int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002487 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2488 SMLoc S = Parser.getTok().getLoc();
2489 const AsmToken &Tok = Parser.getTok();
2490 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2491
Benjamin Kramer59085362011-11-06 20:37:06 +00002492 std::string lowerCase = Tok.getString().lower();
Owen Anderson00828302011-03-18 22:50:18 +00002493 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbachaf4edea2011-12-07 23:40:58 +00002494 .Case("asl", ARM_AM::lsl)
Owen Anderson00828302011-03-18 22:50:18 +00002495 .Case("lsl", ARM_AM::lsl)
2496 .Case("lsr", ARM_AM::lsr)
2497 .Case("asr", ARM_AM::asr)
2498 .Case("ror", ARM_AM::ror)
2499 .Case("rrx", ARM_AM::rrx)
2500 .Default(ARM_AM::no_shift);
2501
2502 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002503 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002504
Jim Grosbache8606dc2011-07-13 17:50:29 +00002505 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002506
Jim Grosbache8606dc2011-07-13 17:50:29 +00002507 // The source register for the shift has already been added to the
2508 // operand list, so we need to pop it off and combine it into the shifted
2509 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002510 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002511 if (!PrevOp->isReg())
2512 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2513 int SrcReg = PrevOp->getReg();
2514 int64_t Imm = 0;
2515 int ShiftReg = 0;
2516 if (ShiftTy == ARM_AM::rrx) {
2517 // RRX Doesn't have an explicit shift amount. The encoder expects
2518 // the shift register to be the same as the source register. Seems odd,
2519 // but OK.
2520 ShiftReg = SrcReg;
2521 } else {
2522 // Figure out if this is shifted by a constant or a register (for non-RRX).
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00002523 if (Parser.getTok().is(AsmToken::Hash) ||
2524 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbache8606dc2011-07-13 17:50:29 +00002525 Parser.Lex(); // Eat hash.
2526 SMLoc ImmLoc = Parser.getTok().getLoc();
2527 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002528 if (getParser().ParseExpression(ShiftExpr)) {
2529 Error(ImmLoc, "invalid immediate shift value");
2530 return -1;
2531 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002532 // The expression must be evaluatable as an immediate.
2533 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002534 if (!CE) {
2535 Error(ImmLoc, "invalid immediate shift value");
2536 return -1;
2537 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002538 // Range check the immediate.
2539 // lsl, ror: 0 <= imm <= 31
2540 // lsr, asr: 0 <= imm <= 32
2541 Imm = CE->getValue();
2542 if (Imm < 0 ||
2543 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2544 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002545 Error(ImmLoc, "immediate shift value out of range");
2546 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002547 }
Jim Grosbachde626ad2011-12-22 17:37:00 +00002548 // shift by zero is a nop. Always send it through as lsl.
2549 // ('as' compatibility)
2550 if (Imm == 0)
2551 ShiftTy = ARM_AM::lsl;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002552 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002553 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002554 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002555 if (ShiftReg == -1) {
2556 Error (L, "expected immediate or register in shift operand");
2557 return -1;
2558 }
2559 } else {
2560 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002561 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002562 return -1;
2563 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002564 }
2565
Owen Anderson92a20222011-07-21 18:54:16 +00002566 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2567 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002568 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002569 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002570 else
2571 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2572 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002573
Jim Grosbach19906722011-07-13 18:49:30 +00002574 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002575}
2576
2577
Bill Wendling50d0f582010-11-18 23:43:05 +00002578/// Try to parse a register name. The token must be an Identifier when called.
2579/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2580/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002581///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002582/// TODO this is likely to change to allow different register types and or to
2583/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002584bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002585tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002586 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002587 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002588 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002589 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002590
Bill Wendling50d0f582010-11-18 23:43:05 +00002591 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002592
Chris Lattnere5658fa2010-10-30 04:09:10 +00002593 const AsmToken &ExclaimTok = Parser.getTok();
2594 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002595 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2596 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002597 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002598 return false;
2599 }
2600
2601 // Also check for an index operand. This is only legal for vector registers,
2602 // but that'll get caught OK in operand matching, so we don't need to
2603 // explicitly filter everything else out here.
2604 if (Parser.getTok().is(AsmToken::LBrac)) {
2605 SMLoc SIdx = Parser.getTok().getLoc();
2606 Parser.Lex(); // Eat left bracket token.
2607
2608 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002609 if (getParser().ParseExpression(ImmVal))
Jim Grosbach24dda212012-01-31 23:51:09 +00002610 return true;
Jim Grosbach460a9052011-10-07 23:56:00 +00002611 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbachef4d3eb2012-01-26 15:56:45 +00002612 if (!MCE)
2613 return TokError("immediate value expected for vector index");
Jim Grosbach460a9052011-10-07 23:56:00 +00002614
2615 SMLoc E = Parser.getTok().getLoc();
Jim Grosbachef4d3eb2012-01-26 15:56:45 +00002616 if (Parser.getTok().isNot(AsmToken::RBrac))
2617 return Error(E, "']' expected");
Jim Grosbach460a9052011-10-07 23:56:00 +00002618
2619 Parser.Lex(); // Eat right bracket token.
2620
2621 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2622 SIdx, E,
2623 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002624 }
2625
Bill Wendling50d0f582010-11-18 23:43:05 +00002626 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002627}
2628
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002629/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2630/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2631/// "c5", ...
2632static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002633 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2634 // but efficient.
2635 switch (Name.size()) {
David Blaikie4d6ccb52012-01-20 21:51:11 +00002636 default: return -1;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002637 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002638 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002639 return -1;
2640 switch (Name[1]) {
2641 default: return -1;
2642 case '0': return 0;
2643 case '1': return 1;
2644 case '2': return 2;
2645 case '3': return 3;
2646 case '4': return 4;
2647 case '5': return 5;
2648 case '6': return 6;
2649 case '7': return 7;
2650 case '8': return 8;
2651 case '9': return 9;
2652 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002653 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002654 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002655 return -1;
2656 switch (Name[2]) {
2657 default: return -1;
2658 case '0': return 10;
2659 case '1': return 11;
2660 case '2': return 12;
2661 case '3': return 13;
2662 case '4': return 14;
2663 case '5': return 15;
2664 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002665 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002666}
2667
Jim Grosbach89df9962011-08-26 21:43:41 +00002668/// parseITCondCode - Try to parse a condition code for an IT instruction.
2669ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2670parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2671 SMLoc S = Parser.getTok().getLoc();
2672 const AsmToken &Tok = Parser.getTok();
2673 if (!Tok.is(AsmToken::Identifier))
2674 return MatchOperand_NoMatch;
2675 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2676 .Case("eq", ARMCC::EQ)
2677 .Case("ne", ARMCC::NE)
2678 .Case("hs", ARMCC::HS)
2679 .Case("cs", ARMCC::HS)
2680 .Case("lo", ARMCC::LO)
2681 .Case("cc", ARMCC::LO)
2682 .Case("mi", ARMCC::MI)
2683 .Case("pl", ARMCC::PL)
2684 .Case("vs", ARMCC::VS)
2685 .Case("vc", ARMCC::VC)
2686 .Case("hi", ARMCC::HI)
2687 .Case("ls", ARMCC::LS)
2688 .Case("ge", ARMCC::GE)
2689 .Case("lt", ARMCC::LT)
2690 .Case("gt", ARMCC::GT)
2691 .Case("le", ARMCC::LE)
2692 .Case("al", ARMCC::AL)
2693 .Default(~0U);
2694 if (CC == ~0U)
2695 return MatchOperand_NoMatch;
2696 Parser.Lex(); // Eat the token.
2697
2698 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2699
2700 return MatchOperand_Success;
2701}
2702
Jim Grosbach43904292011-07-25 20:14:50 +00002703/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002704/// token must be an Identifier when called, and if it is a coprocessor
2705/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002706ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002707parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002708 SMLoc S = Parser.getTok().getLoc();
2709 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002710 if (Tok.isNot(AsmToken::Identifier))
2711 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002712
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002713 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002714 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002715 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002716
2717 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002718 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002719 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002720}
2721
Jim Grosbach43904292011-07-25 20:14:50 +00002722/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002723/// token must be an Identifier when called, and if it is a coprocessor
2724/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002725ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002726parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002727 SMLoc S = Parser.getTok().getLoc();
2728 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002729 if (Tok.isNot(AsmToken::Identifier))
2730 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002731
2732 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2733 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002734 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002735
2736 Parser.Lex(); // Eat identifier token.
2737 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002738 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002739}
2740
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002741/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2742/// coproc_option : '{' imm0_255 '}'
2743ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2744parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2745 SMLoc S = Parser.getTok().getLoc();
2746
2747 // If this isn't a '{', this isn't a coprocessor immediate operand.
2748 if (Parser.getTok().isNot(AsmToken::LCurly))
2749 return MatchOperand_NoMatch;
2750 Parser.Lex(); // Eat the '{'
2751
2752 const MCExpr *Expr;
2753 SMLoc Loc = Parser.getTok().getLoc();
2754 if (getParser().ParseExpression(Expr)) {
2755 Error(Loc, "illegal expression");
2756 return MatchOperand_ParseFail;
2757 }
2758 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2759 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2760 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2761 return MatchOperand_ParseFail;
2762 }
2763 int Val = CE->getValue();
2764
2765 // Check for and consume the closing '}'
2766 if (Parser.getTok().isNot(AsmToken::RCurly))
2767 return MatchOperand_ParseFail;
2768 SMLoc E = Parser.getTok().getLoc();
2769 Parser.Lex(); // Eat the '}'
2770
2771 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2772 return MatchOperand_Success;
2773}
2774
Jim Grosbachd0588e22011-09-14 18:08:35 +00002775// For register list parsing, we need to map from raw GPR register numbering
2776// to the enumeration values. The enumeration values aren't sorted by
2777// register number due to our using "sp", "lr" and "pc" as canonical names.
2778static unsigned getNextRegister(unsigned Reg) {
2779 // If this is a GPR, we need to do it manually, otherwise we can rely
2780 // on the sort ordering of the enumeration since the other reg-classes
2781 // are sane.
2782 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2783 return Reg + 1;
2784 switch(Reg) {
Craig Topperbc219812012-02-07 02:50:20 +00002785 default: llvm_unreachable("Invalid GPR number!");
Jim Grosbachd0588e22011-09-14 18:08:35 +00002786 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2787 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2788 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2789 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2790 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2791 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2792 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2793 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2794 }
2795}
2796
Jim Grosbachce485e72011-11-11 21:27:40 +00002797// Return the low-subreg of a given Q register.
2798static unsigned getDRegFromQReg(unsigned QReg) {
2799 switch (QReg) {
2800 default: llvm_unreachable("expected a Q register!");
2801 case ARM::Q0: return ARM::D0;
2802 case ARM::Q1: return ARM::D2;
2803 case ARM::Q2: return ARM::D4;
2804 case ARM::Q3: return ARM::D6;
2805 case ARM::Q4: return ARM::D8;
2806 case ARM::Q5: return ARM::D10;
2807 case ARM::Q6: return ARM::D12;
2808 case ARM::Q7: return ARM::D14;
2809 case ARM::Q8: return ARM::D16;
Jim Grosbach25e0a872011-11-15 21:01:30 +00002810 case ARM::Q9: return ARM::D18;
Jim Grosbachce485e72011-11-11 21:27:40 +00002811 case ARM::Q10: return ARM::D20;
2812 case ARM::Q11: return ARM::D22;
2813 case ARM::Q12: return ARM::D24;
2814 case ARM::Q13: return ARM::D26;
2815 case ARM::Q14: return ARM::D28;
2816 case ARM::Q15: return ARM::D30;
2817 }
2818}
2819
Jim Grosbachd0588e22011-09-14 18:08:35 +00002820/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002821bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002822parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002823 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002824 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002825 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002826 Parser.Lex(); // Eat '{' token.
2827 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002828
Jim Grosbachd0588e22011-09-14 18:08:35 +00002829 // Check the first register in the list to see what register class
2830 // this is a list of.
2831 int Reg = tryParseRegister();
2832 if (Reg == -1)
2833 return Error(RegLoc, "register expected");
2834
Jim Grosbachce485e72011-11-11 21:27:40 +00002835 // The reglist instructions have at most 16 registers, so reserve
2836 // space for that many.
2837 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2838
2839 // Allow Q regs and just interpret them as the two D sub-registers.
2840 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2841 Reg = getDRegFromQReg(Reg);
2842 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2843 ++Reg;
2844 }
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002845 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002846 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2847 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2848 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2849 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2850 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2851 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2852 else
2853 return Error(RegLoc, "invalid register in register list");
2854
Jim Grosbachce485e72011-11-11 21:27:40 +00002855 // Store the register.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002856 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002857
Jim Grosbachd0588e22011-09-14 18:08:35 +00002858 // This starts immediately after the first register token in the list,
2859 // so we can see either a comma or a minus (range separator) as a legal
2860 // next token.
2861 while (Parser.getTok().is(AsmToken::Comma) ||
2862 Parser.getTok().is(AsmToken::Minus)) {
2863 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache43862b2011-11-15 23:19:15 +00002864 Parser.Lex(); // Eat the minus.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002865 SMLoc EndLoc = Parser.getTok().getLoc();
2866 int EndReg = tryParseRegister();
2867 if (EndReg == -1)
2868 return Error(EndLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002869 // Allow Q regs and just interpret them as the two D sub-registers.
2870 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2871 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002872 // If the register is the same as the start reg, there's nothing
2873 // more to do.
2874 if (Reg == EndReg)
2875 continue;
2876 // The register must be in the same register class as the first.
2877 if (!RC->contains(EndReg))
2878 return Error(EndLoc, "invalid register in register list");
2879 // Ranges must go from low to high.
2880 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2881 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002882
Jim Grosbachd0588e22011-09-14 18:08:35 +00002883 // Add all the registers in the range to the register list.
2884 while (Reg != EndReg) {
2885 Reg = getNextRegister(Reg);
2886 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2887 }
2888 continue;
2889 }
2890 Parser.Lex(); // Eat the comma.
2891 RegLoc = Parser.getTok().getLoc();
2892 int OldReg = Reg;
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002893 const AsmToken RegTok = Parser.getTok();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002894 Reg = tryParseRegister();
2895 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002896 return Error(RegLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002897 // Allow Q regs and just interpret them as the two D sub-registers.
2898 bool isQReg = false;
2899 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2900 Reg = getDRegFromQReg(Reg);
2901 isQReg = true;
2902 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002903 // The register must be in the same register class as the first.
2904 if (!RC->contains(Reg))
2905 return Error(RegLoc, "invalid register in register list");
2906 // List must be monotonically increasing.
Jim Grosbachbe7cf2b2012-03-16 20:48:38 +00002907 if (getARMRegisterNumbering(Reg) < getARMRegisterNumbering(OldReg)) {
2908 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2909 Warning(RegLoc, "register list not in ascending order");
2910 else
2911 return Error(RegLoc, "register list not in ascending order");
2912 }
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002913 if (getARMRegisterNumbering(Reg) == getARMRegisterNumbering(OldReg)) {
2914 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
2915 ") in register list");
2916 continue;
2917 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002918 // VFP register lists must also be contiguous.
2919 // It's OK to use the enumeration values directly here rather, as the
2920 // VFP register classes have the enum sorted properly.
2921 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2922 Reg != OldReg + 1)
2923 return Error(RegLoc, "non-contiguous register range");
2924 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbachce485e72011-11-11 21:27:40 +00002925 if (isQReg)
2926 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002927 }
2928
Jim Grosbachd0588e22011-09-14 18:08:35 +00002929 SMLoc E = Parser.getTok().getLoc();
2930 if (Parser.getTok().isNot(AsmToken::RCurly))
2931 return Error(E, "'}' expected");
2932 Parser.Lex(); // Eat '}' token.
2933
Jim Grosbach27debd62011-12-13 21:48:29 +00002934 // Push the register list operand.
Bill Wendling50d0f582010-11-18 23:43:05 +00002935 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
Jim Grosbach27debd62011-12-13 21:48:29 +00002936
2937 // The ARM system instruction variants for LDM/STM have a '^' token here.
2938 if (Parser.getTok().is(AsmToken::Caret)) {
2939 Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
2940 Parser.Lex(); // Eat '^' token.
2941 }
2942
Bill Wendling50d0f582010-11-18 23:43:05 +00002943 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002944}
2945
Jim Grosbach98b05a52011-11-30 01:09:44 +00002946// Helper function to parse the lane index for vector lists.
2947ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach7636bf62011-12-02 00:35:16 +00002948parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2949 Index = 0; // Always return a defined index value.
Jim Grosbach98b05a52011-11-30 01:09:44 +00002950 if (Parser.getTok().is(AsmToken::LBrac)) {
2951 Parser.Lex(); // Eat the '['.
2952 if (Parser.getTok().is(AsmToken::RBrac)) {
2953 // "Dn[]" is the 'all lanes' syntax.
2954 LaneKind = AllLanes;
2955 Parser.Lex(); // Eat the ']'.
2956 return MatchOperand_Success;
2957 }
Jim Grosbachceee9842012-03-19 20:39:53 +00002958
2959 // There's an optional '#' token here. Normally there wouldn't be, but
2960 // inline assemble puts one in, and it's friendly to accept that.
2961 if (Parser.getTok().is(AsmToken::Hash))
2962 Parser.Lex(); // Eat the '#'
2963
Jim Grosbachc9313252011-12-21 01:19:23 +00002964 const MCExpr *LaneIndex;
2965 SMLoc Loc = Parser.getTok().getLoc();
2966 if (getParser().ParseExpression(LaneIndex)) {
2967 Error(Loc, "illegal expression");
2968 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002969 }
Jim Grosbachc9313252011-12-21 01:19:23 +00002970 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LaneIndex);
2971 if (!CE) {
2972 Error(Loc, "lane index must be empty or an integer");
2973 return MatchOperand_ParseFail;
2974 }
2975 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2976 Error(Parser.getTok().getLoc(), "']' expected");
2977 return MatchOperand_ParseFail;
2978 }
2979 Parser.Lex(); // Eat the ']'.
2980 int64_t Val = CE->getValue();
2981
2982 // FIXME: Make this range check context sensitive for .8, .16, .32.
2983 if (Val < 0 || Val > 7) {
2984 Error(Parser.getTok().getLoc(), "lane index out of range");
2985 return MatchOperand_ParseFail;
2986 }
2987 Index = Val;
2988 LaneKind = IndexedLane;
2989 return MatchOperand_Success;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002990 }
2991 LaneKind = NoLanes;
2992 return MatchOperand_Success;
2993}
2994
Jim Grosbach862019c2011-10-18 23:02:30 +00002995// parse a vector register list
2996ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2997parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002998 VectorLaneTy LaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002999 unsigned LaneIndex;
Jim Grosbach5c984e42011-11-15 21:45:55 +00003000 SMLoc S = Parser.getTok().getLoc();
3001 // As an extension (to match gas), support a plain D register or Q register
3002 // (without encosing curly braces) as a single or double entry list,
3003 // respectively.
3004 if (Parser.getTok().is(AsmToken::Identifier)) {
3005 int Reg = tryParseRegister();
3006 if (Reg == -1)
3007 return MatchOperand_NoMatch;
3008 SMLoc E = Parser.getTok().getLoc();
3009 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00003010 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00003011 if (Res != MatchOperand_Success)
3012 return Res;
3013 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003014 case NoLanes:
3015 E = Parser.getTok().getLoc();
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003016 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003017 break;
3018 case AllLanes:
3019 E = Parser.getTok().getLoc();
Jim Grosbach3471d4f2011-12-21 00:38:54 +00003020 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false,
3021 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003022 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003023 case IndexedLane:
3024 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00003025 LaneIndex,
3026 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00003027 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003028 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00003029 return MatchOperand_Success;
3030 }
3031 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
3032 Reg = getDRegFromQReg(Reg);
Jim Grosbach7636bf62011-12-02 00:35:16 +00003033 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00003034 if (Res != MatchOperand_Success)
3035 return Res;
3036 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003037 case NoLanes:
3038 E = Parser.getTok().getLoc();
Jim Grosbach28f08c92012-03-05 19:33:30 +00003039 Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0,
Jim Grosbachc0fc4502012-03-06 22:01:44 +00003040 &ARMMCRegisterClasses[ARM::DPairRegClassID]);
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003041 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003042 break;
3043 case AllLanes:
3044 E = Parser.getTok().getLoc();
Jim Grosbachc0fc4502012-03-06 22:01:44 +00003045 Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0,
3046 &ARMMCRegisterClasses[ARM::DPairRegClassID]);
Jim Grosbach3471d4f2011-12-21 00:38:54 +00003047 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, false,
3048 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003049 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003050 case IndexedLane:
3051 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00003052 LaneIndex,
3053 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00003054 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003055 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00003056 return MatchOperand_Success;
3057 }
3058 Error(S, "vector register expected");
3059 return MatchOperand_ParseFail;
3060 }
3061
3062 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbach862019c2011-10-18 23:02:30 +00003063 return MatchOperand_NoMatch;
3064
Jim Grosbach862019c2011-10-18 23:02:30 +00003065 Parser.Lex(); // Eat '{' token.
3066 SMLoc RegLoc = Parser.getTok().getLoc();
3067
3068 int Reg = tryParseRegister();
3069 if (Reg == -1) {
3070 Error(RegLoc, "register expected");
3071 return MatchOperand_ParseFail;
3072 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003073 unsigned Count = 1;
Jim Grosbach276ed032011-12-15 21:54:55 +00003074 int Spacing = 0;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003075 unsigned FirstReg = Reg;
3076 // The list is of D registers, but we also allow Q regs and just interpret
3077 // them as the two D sub-registers.
3078 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
3079 FirstReg = Reg = getDRegFromQReg(Reg);
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003080 Spacing = 1; // double-spacing requires explicit D registers, otherwise
3081 // it's ambiguous with four-register single spaced.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003082 ++Reg;
3083 ++Count;
3084 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00003085 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003086 return MatchOperand_ParseFail;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003087
Jim Grosbache43862b2011-11-15 23:19:15 +00003088 while (Parser.getTok().is(AsmToken::Comma) ||
3089 Parser.getTok().is(AsmToken::Minus)) {
3090 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003091 if (!Spacing)
3092 Spacing = 1; // Register range implies a single spaced list.
3093 else if (Spacing == 2) {
3094 Error(Parser.getTok().getLoc(),
3095 "sequential registers in double spaced list");
3096 return MatchOperand_ParseFail;
3097 }
Jim Grosbache43862b2011-11-15 23:19:15 +00003098 Parser.Lex(); // Eat the minus.
3099 SMLoc EndLoc = Parser.getTok().getLoc();
3100 int EndReg = tryParseRegister();
3101 if (EndReg == -1) {
3102 Error(EndLoc, "register expected");
3103 return MatchOperand_ParseFail;
3104 }
3105 // Allow Q regs and just interpret them as the two D sub-registers.
3106 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
3107 EndReg = getDRegFromQReg(EndReg) + 1;
3108 // If the register is the same as the start reg, there's nothing
3109 // more to do.
3110 if (Reg == EndReg)
3111 continue;
3112 // The register must be in the same register class as the first.
3113 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
3114 Error(EndLoc, "invalid register in register list");
3115 return MatchOperand_ParseFail;
3116 }
3117 // Ranges must go from low to high.
3118 if (Reg > EndReg) {
3119 Error(EndLoc, "bad range in register list");
3120 return MatchOperand_ParseFail;
3121 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00003122 // Parse the lane specifier if present.
3123 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003124 unsigned NextLaneIndex;
3125 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003126 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003127 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003128 Error(EndLoc, "mismatched lane index in register list");
3129 return MatchOperand_ParseFail;
3130 }
3131 EndLoc = Parser.getTok().getLoc();
Jim Grosbache43862b2011-11-15 23:19:15 +00003132
3133 // Add all the registers in the range to the register list.
3134 Count += EndReg - Reg;
3135 Reg = EndReg;
3136 continue;
3137 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003138 Parser.Lex(); // Eat the comma.
3139 RegLoc = Parser.getTok().getLoc();
3140 int OldReg = Reg;
3141 Reg = tryParseRegister();
3142 if (Reg == -1) {
3143 Error(RegLoc, "register expected");
3144 return MatchOperand_ParseFail;
3145 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003146 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00003147 // It's OK to use the enumeration values directly here rather, as the
3148 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003149 //
3150 // The list is of D registers, but we also allow Q regs and just interpret
3151 // them as the two D sub-registers.
3152 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003153 if (!Spacing)
3154 Spacing = 1; // Register range implies a single spaced list.
3155 else if (Spacing == 2) {
3156 Error(RegLoc,
3157 "invalid register in double-spaced list (must be 'D' register')");
3158 return MatchOperand_ParseFail;
3159 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003160 Reg = getDRegFromQReg(Reg);
3161 if (Reg != OldReg + 1) {
3162 Error(RegLoc, "non-contiguous register range");
3163 return MatchOperand_ParseFail;
3164 }
3165 ++Reg;
3166 Count += 2;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003167 // Parse the lane specifier if present.
3168 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003169 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003170 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003171 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003172 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003173 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003174 Error(EndLoc, "mismatched lane index in register list");
3175 return MatchOperand_ParseFail;
3176 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003177 continue;
3178 }
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003179 // Normal D register.
3180 // Figure out the register spacing (single or double) of the list if
3181 // we don't know it already.
3182 if (!Spacing)
3183 Spacing = 1 + (Reg == OldReg + 2);
3184
3185 // Just check that it's contiguous and keep going.
3186 if (Reg != OldReg + Spacing) {
Jim Grosbach862019c2011-10-18 23:02:30 +00003187 Error(RegLoc, "non-contiguous register range");
3188 return MatchOperand_ParseFail;
3189 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003190 ++Count;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003191 // Parse the lane specifier if present.
3192 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003193 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003194 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003195 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003196 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003197 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003198 Error(EndLoc, "mismatched lane index in register list");
3199 return MatchOperand_ParseFail;
3200 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003201 }
3202
3203 SMLoc E = Parser.getTok().getLoc();
3204 if (Parser.getTok().isNot(AsmToken::RCurly)) {
3205 Error(E, "'}' expected");
3206 return MatchOperand_ParseFail;
3207 }
3208 Parser.Lex(); // Eat '}' token.
3209
Jim Grosbach98b05a52011-11-30 01:09:44 +00003210 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003211 case NoLanes:
Jim Grosbachc0fc4502012-03-06 22:01:44 +00003212 // Two-register operands have been converted to the
Jim Grosbachc3384c92012-03-05 21:43:40 +00003213 // composite register classes.
3214 if (Count == 2) {
3215 const MCRegisterClass *RC = (Spacing == 1) ?
3216 &ARMMCRegisterClasses[ARM::DPairRegClassID] :
3217 &ARMMCRegisterClasses[ARM::DPairSpcRegClassID];
3218 FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC);
3219 }
Jim Grosbach28f08c92012-03-05 19:33:30 +00003220
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003221 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count,
3222 (Spacing == 2), S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003223 break;
3224 case AllLanes:
Jim Grosbachc0fc4502012-03-06 22:01:44 +00003225 // Two-register operands have been converted to the
3226 // composite register classes.
Jim Grosbach4d0983a2012-03-06 23:10:38 +00003227 if (Count == 2) {
3228 const MCRegisterClass *RC = (Spacing == 1) ?
3229 &ARMMCRegisterClasses[ARM::DPairRegClassID] :
3230 &ARMMCRegisterClasses[ARM::DPairSpcRegClassID];
Jim Grosbachc0fc4502012-03-06 22:01:44 +00003231 FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC);
3232 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00003233 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00003234 (Spacing == 2),
Jim Grosbach98b05a52011-11-30 01:09:44 +00003235 S, E));
3236 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003237 case IndexedLane:
3238 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00003239 LaneIndex,
3240 (Spacing == 2),
3241 S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00003242 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003243 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003244 return MatchOperand_Success;
3245}
3246
Jim Grosbach43904292011-07-25 20:14:50 +00003247/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00003248ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003249parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003250 SMLoc S = Parser.getTok().getLoc();
3251 const AsmToken &Tok = Parser.getTok();
3252 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3253 StringRef OptStr = Tok.getString();
3254
3255 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
3256 .Case("sy", ARM_MB::SY)
3257 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003258 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003259 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003260 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003261 .Case("ishst", ARM_MB::ISHST)
3262 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003263 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003264 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003265 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003266 .Case("osh", ARM_MB::OSH)
3267 .Case("oshst", ARM_MB::OSHST)
3268 .Default(~0U);
3269
3270 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00003271 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003272
3273 Parser.Lex(); // Eat identifier token.
3274 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00003275 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003276}
3277
Jim Grosbach43904292011-07-25 20:14:50 +00003278/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003279ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003280parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003281 SMLoc S = Parser.getTok().getLoc();
3282 const AsmToken &Tok = Parser.getTok();
3283 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3284 StringRef IFlagsStr = Tok.getString();
3285
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003286 // An iflags string of "none" is interpreted to mean that none of the AIF
3287 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003288 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003289 if (IFlagsStr != "none") {
3290 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
3291 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
3292 .Case("a", ARM_PROC::A)
3293 .Case("i", ARM_PROC::I)
3294 .Case("f", ARM_PROC::F)
3295 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003296
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003297 // If some specific iflag is already set, it means that some letter is
3298 // present more than once, this is not acceptable.
3299 if (Flag == ~0U || (IFlags & Flag))
3300 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003301
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003302 IFlags |= Flag;
3303 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003304 }
3305
3306 Parser.Lex(); // Eat identifier token.
3307 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
3308 return MatchOperand_Success;
3309}
3310
Jim Grosbach43904292011-07-25 20:14:50 +00003311/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003312ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003313parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003314 SMLoc S = Parser.getTok().getLoc();
3315 const AsmToken &Tok = Parser.getTok();
3316 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3317 StringRef Mask = Tok.getString();
3318
James Molloyacad68d2011-09-28 14:21:38 +00003319 if (isMClass()) {
3320 // See ARMv6-M 10.1.1
Jim Grosbachb84ad4a2012-03-15 21:34:14 +00003321 std::string Name = Mask.lower();
3322 unsigned FlagsVal = StringSwitch<unsigned>(Name)
James Molloyacad68d2011-09-28 14:21:38 +00003323 .Case("apsr", 0)
3324 .Case("iapsr", 1)
3325 .Case("eapsr", 2)
3326 .Case("xpsr", 3)
3327 .Case("ipsr", 5)
3328 .Case("epsr", 6)
3329 .Case("iepsr", 7)
3330 .Case("msp", 8)
3331 .Case("psp", 9)
3332 .Case("primask", 16)
3333 .Case("basepri", 17)
3334 .Case("basepri_max", 18)
3335 .Case("faultmask", 19)
3336 .Case("control", 20)
3337 .Default(~0U);
Jim Grosbach18c8d122011-12-22 17:17:10 +00003338
James Molloyacad68d2011-09-28 14:21:38 +00003339 if (FlagsVal == ~0U)
3340 return MatchOperand_NoMatch;
3341
3342 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
3343 // basepri, basepri_max and faultmask only valid for V7m.
3344 return MatchOperand_NoMatch;
Jim Grosbach18c8d122011-12-22 17:17:10 +00003345
James Molloyacad68d2011-09-28 14:21:38 +00003346 Parser.Lex(); // Eat identifier token.
3347 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3348 return MatchOperand_Success;
3349 }
3350
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003351 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
3352 size_t Start = 0, Next = Mask.find('_');
3353 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00003354 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003355 if (Next != StringRef::npos)
3356 Flags = Mask.slice(Next+1, Mask.size());
3357
3358 // FlagsVal contains the complete mask:
3359 // 3-0: Mask
3360 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3361 unsigned FlagsVal = 0;
3362
3363 if (SpecReg == "apsr") {
3364 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00003365 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003366 .Case("g", 0x4) // same as CPSR_s
3367 .Case("nzcvqg", 0xc) // same as CPSR_fs
3368 .Default(~0U);
3369
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003370 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003371 if (!Flags.empty())
3372 return MatchOperand_NoMatch;
3373 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00003374 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003375 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003376 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Jim Grosbachb657a902012-04-05 03:17:53 +00003377 // cpsr_all is an alias for cpsr_fc, as is plain cpsr.
3378 if (Flags == "all" || Flags == "")
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00003379 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003380 for (int i = 0, e = Flags.size(); i != e; ++i) {
3381 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
3382 .Case("c", 1)
3383 .Case("x", 2)
3384 .Case("s", 4)
3385 .Case("f", 8)
3386 .Default(~0U);
3387
3388 // If some specific flag is already set, it means that some letter is
3389 // present more than once, this is not acceptable.
3390 if (FlagsVal == ~0U || (FlagsVal & Flag))
3391 return MatchOperand_NoMatch;
3392 FlagsVal |= Flag;
3393 }
3394 } else // No match for special register.
3395 return MatchOperand_NoMatch;
3396
Owen Anderson7784f1d2011-10-21 18:43:28 +00003397 // Special register without flags is NOT equivalent to "fc" flags.
3398 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3399 // two lines would enable gas compatibility at the expense of breaking
3400 // round-tripping.
3401 //
3402 // if (!FlagsVal)
3403 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003404
3405 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3406 if (SpecReg == "spsr")
3407 FlagsVal |= 16;
3408
3409 Parser.Lex(); // Eat identifier token.
3410 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3411 return MatchOperand_Success;
3412}
3413
Jim Grosbachf6c05252011-07-21 17:23:04 +00003414ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3415parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3416 int Low, int High) {
3417 const AsmToken &Tok = Parser.getTok();
3418 if (Tok.isNot(AsmToken::Identifier)) {
3419 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3420 return MatchOperand_ParseFail;
3421 }
3422 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00003423 std::string LowerOp = Op.lower();
3424 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00003425 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3426 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3427 return MatchOperand_ParseFail;
3428 }
3429 Parser.Lex(); // Eat shift type token.
3430
3431 // There must be a '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003432 if (Parser.getTok().isNot(AsmToken::Hash) &&
3433 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbachf6c05252011-07-21 17:23:04 +00003434 Error(Parser.getTok().getLoc(), "'#' expected");
3435 return MatchOperand_ParseFail;
3436 }
3437 Parser.Lex(); // Eat hash token.
3438
3439 const MCExpr *ShiftAmount;
3440 SMLoc Loc = Parser.getTok().getLoc();
3441 if (getParser().ParseExpression(ShiftAmount)) {
3442 Error(Loc, "illegal expression");
3443 return MatchOperand_ParseFail;
3444 }
3445 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3446 if (!CE) {
3447 Error(Loc, "constant expression expected");
3448 return MatchOperand_ParseFail;
3449 }
3450 int Val = CE->getValue();
3451 if (Val < Low || Val > High) {
3452 Error(Loc, "immediate value out of range");
3453 return MatchOperand_ParseFail;
3454 }
3455
3456 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3457
3458 return MatchOperand_Success;
3459}
3460
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003461ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3462parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3463 const AsmToken &Tok = Parser.getTok();
3464 SMLoc S = Tok.getLoc();
3465 if (Tok.isNot(AsmToken::Identifier)) {
3466 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3467 return MatchOperand_ParseFail;
3468 }
3469 int Val = StringSwitch<int>(Tok.getString())
3470 .Case("be", 1)
3471 .Case("le", 0)
3472 .Default(-1);
3473 Parser.Lex(); // Eat the token.
3474
3475 if (Val == -1) {
3476 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3477 return MatchOperand_ParseFail;
3478 }
3479 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3480 getContext()),
3481 S, Parser.getTok().getLoc()));
3482 return MatchOperand_Success;
3483}
3484
Jim Grosbach580f4a92011-07-25 22:20:28 +00003485/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3486/// instructions. Legal values are:
3487/// lsl #n 'n' in [0,31]
3488/// asr #n 'n' in [1,32]
3489/// n == 32 encoded as n == 0.
3490ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3491parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3492 const AsmToken &Tok = Parser.getTok();
3493 SMLoc S = Tok.getLoc();
3494 if (Tok.isNot(AsmToken::Identifier)) {
3495 Error(S, "shift operator 'asr' or 'lsl' expected");
3496 return MatchOperand_ParseFail;
3497 }
3498 StringRef ShiftName = Tok.getString();
3499 bool isASR;
3500 if (ShiftName == "lsl" || ShiftName == "LSL")
3501 isASR = false;
3502 else if (ShiftName == "asr" || ShiftName == "ASR")
3503 isASR = true;
3504 else {
3505 Error(S, "shift operator 'asr' or 'lsl' expected");
3506 return MatchOperand_ParseFail;
3507 }
3508 Parser.Lex(); // Eat the operator.
3509
3510 // A '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003511 if (Parser.getTok().isNot(AsmToken::Hash) &&
3512 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach580f4a92011-07-25 22:20:28 +00003513 Error(Parser.getTok().getLoc(), "'#' expected");
3514 return MatchOperand_ParseFail;
3515 }
3516 Parser.Lex(); // Eat hash token.
3517
3518 const MCExpr *ShiftAmount;
3519 SMLoc E = Parser.getTok().getLoc();
3520 if (getParser().ParseExpression(ShiftAmount)) {
3521 Error(E, "malformed shift expression");
3522 return MatchOperand_ParseFail;
3523 }
3524 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3525 if (!CE) {
3526 Error(E, "shift amount must be an immediate");
3527 return MatchOperand_ParseFail;
3528 }
3529
3530 int64_t Val = CE->getValue();
3531 if (isASR) {
3532 // Shift amount must be in [1,32]
3533 if (Val < 1 || Val > 32) {
3534 Error(E, "'asr' shift amount must be in range [1,32]");
3535 return MatchOperand_ParseFail;
3536 }
Owen Anderson0afa0092011-09-26 21:06:22 +00003537 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3538 if (isThumb() && Val == 32) {
3539 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3540 return MatchOperand_ParseFail;
3541 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00003542 if (Val == 32) Val = 0;
3543 } else {
3544 // Shift amount must be in [1,32]
3545 if (Val < 0 || Val > 31) {
3546 Error(E, "'lsr' shift amount must be in range [0,31]");
3547 return MatchOperand_ParseFail;
3548 }
3549 }
3550
3551 E = Parser.getTok().getLoc();
3552 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3553
3554 return MatchOperand_Success;
3555}
3556
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003557/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3558/// of instructions. Legal values are:
3559/// ror #n 'n' in {0, 8, 16, 24}
3560ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3561parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3562 const AsmToken &Tok = Parser.getTok();
3563 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00003564 if (Tok.isNot(AsmToken::Identifier))
3565 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003566 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00003567 if (ShiftName != "ror" && ShiftName != "ROR")
3568 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003569 Parser.Lex(); // Eat the operator.
3570
3571 // A '#' and a rotate amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003572 if (Parser.getTok().isNot(AsmToken::Hash) &&
3573 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003574 Error(Parser.getTok().getLoc(), "'#' expected");
3575 return MatchOperand_ParseFail;
3576 }
3577 Parser.Lex(); // Eat hash token.
3578
3579 const MCExpr *ShiftAmount;
3580 SMLoc E = Parser.getTok().getLoc();
3581 if (getParser().ParseExpression(ShiftAmount)) {
3582 Error(E, "malformed rotate expression");
3583 return MatchOperand_ParseFail;
3584 }
3585 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3586 if (!CE) {
3587 Error(E, "rotate amount must be an immediate");
3588 return MatchOperand_ParseFail;
3589 }
3590
3591 int64_t Val = CE->getValue();
3592 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3593 // normally, zero is represented in asm by omitting the rotate operand
3594 // entirely.
3595 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3596 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3597 return MatchOperand_ParseFail;
3598 }
3599
3600 E = Parser.getTok().getLoc();
3601 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3602
3603 return MatchOperand_Success;
3604}
3605
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003606ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3607parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3608 SMLoc S = Parser.getTok().getLoc();
3609 // The bitfield descriptor is really two operands, the LSB and the width.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003610 if (Parser.getTok().isNot(AsmToken::Hash) &&
3611 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003612 Error(Parser.getTok().getLoc(), "'#' expected");
3613 return MatchOperand_ParseFail;
3614 }
3615 Parser.Lex(); // Eat hash token.
3616
3617 const MCExpr *LSBExpr;
3618 SMLoc E = Parser.getTok().getLoc();
3619 if (getParser().ParseExpression(LSBExpr)) {
3620 Error(E, "malformed immediate expression");
3621 return MatchOperand_ParseFail;
3622 }
3623 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3624 if (!CE) {
3625 Error(E, "'lsb' operand must be an immediate");
3626 return MatchOperand_ParseFail;
3627 }
3628
3629 int64_t LSB = CE->getValue();
3630 // The LSB must be in the range [0,31]
3631 if (LSB < 0 || LSB > 31) {
3632 Error(E, "'lsb' operand must be in the range [0,31]");
3633 return MatchOperand_ParseFail;
3634 }
3635 E = Parser.getTok().getLoc();
3636
3637 // Expect another immediate operand.
3638 if (Parser.getTok().isNot(AsmToken::Comma)) {
3639 Error(Parser.getTok().getLoc(), "too few operands");
3640 return MatchOperand_ParseFail;
3641 }
3642 Parser.Lex(); // Eat hash token.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003643 if (Parser.getTok().isNot(AsmToken::Hash) &&
3644 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003645 Error(Parser.getTok().getLoc(), "'#' expected");
3646 return MatchOperand_ParseFail;
3647 }
3648 Parser.Lex(); // Eat hash token.
3649
3650 const MCExpr *WidthExpr;
3651 if (getParser().ParseExpression(WidthExpr)) {
3652 Error(E, "malformed immediate expression");
3653 return MatchOperand_ParseFail;
3654 }
3655 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3656 if (!CE) {
3657 Error(E, "'width' operand must be an immediate");
3658 return MatchOperand_ParseFail;
3659 }
3660
3661 int64_t Width = CE->getValue();
3662 // The LSB must be in the range [1,32-lsb]
3663 if (Width < 1 || Width > 32 - LSB) {
3664 Error(E, "'width' operand must be in the range [1,32-lsb]");
3665 return MatchOperand_ParseFail;
3666 }
3667 E = Parser.getTok().getLoc();
3668
3669 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3670
3671 return MatchOperand_Success;
3672}
3673
Jim Grosbach7ce05792011-08-03 23:50:40 +00003674ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3675parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3676 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003677 // postidx_reg := '+' register {, shift}
3678 // | '-' register {, shift}
3679 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003680
3681 // This method must return MatchOperand_NoMatch without consuming any tokens
3682 // in the case where there is no match, as other alternatives take other
3683 // parse methods.
3684 AsmToken Tok = Parser.getTok();
3685 SMLoc S = Tok.getLoc();
3686 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003687 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003688 int Reg = -1;
3689 if (Tok.is(AsmToken::Plus)) {
3690 Parser.Lex(); // Eat the '+' token.
3691 haveEaten = true;
3692 } else if (Tok.is(AsmToken::Minus)) {
3693 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003694 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003695 haveEaten = true;
3696 }
3697 if (Parser.getTok().is(AsmToken::Identifier))
3698 Reg = tryParseRegister();
3699 if (Reg == -1) {
3700 if (!haveEaten)
3701 return MatchOperand_NoMatch;
3702 Error(Parser.getTok().getLoc(), "register expected");
3703 return MatchOperand_ParseFail;
3704 }
3705 SMLoc E = Parser.getTok().getLoc();
3706
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003707 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3708 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003709 if (Parser.getTok().is(AsmToken::Comma)) {
3710 Parser.Lex(); // Eat the ','.
3711 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3712 return MatchOperand_ParseFail;
3713 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003714
3715 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3716 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003717
3718 return MatchOperand_Success;
3719}
3720
Jim Grosbach251bf252011-08-10 21:56:18 +00003721ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3722parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3723 // Check for a post-index addressing register operand. Specifically:
3724 // am3offset := '+' register
3725 // | '-' register
3726 // | register
3727 // | # imm
3728 // | # + imm
3729 // | # - imm
3730
3731 // This method must return MatchOperand_NoMatch without consuming any tokens
3732 // in the case where there is no match, as other alternatives take other
3733 // parse methods.
3734 AsmToken Tok = Parser.getTok();
3735 SMLoc S = Tok.getLoc();
3736
3737 // Do immediates first, as we always parse those if we have a '#'.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003738 if (Parser.getTok().is(AsmToken::Hash) ||
3739 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach251bf252011-08-10 21:56:18 +00003740 Parser.Lex(); // Eat the '#'.
3741 // Explicitly look for a '-', as we need to encode negative zero
3742 // differently.
3743 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3744 const MCExpr *Offset;
3745 if (getParser().ParseExpression(Offset))
3746 return MatchOperand_ParseFail;
3747 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3748 if (!CE) {
3749 Error(S, "constant expression expected");
3750 return MatchOperand_ParseFail;
3751 }
3752 SMLoc E = Tok.getLoc();
3753 // Negative zero is encoded as the flag value INT32_MIN.
3754 int32_t Val = CE->getValue();
3755 if (isNegative && Val == 0)
3756 Val = INT32_MIN;
3757
3758 Operands.push_back(
3759 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3760
3761 return MatchOperand_Success;
3762 }
3763
3764
3765 bool haveEaten = false;
3766 bool isAdd = true;
3767 int Reg = -1;
3768 if (Tok.is(AsmToken::Plus)) {
3769 Parser.Lex(); // Eat the '+' token.
3770 haveEaten = true;
3771 } else if (Tok.is(AsmToken::Minus)) {
3772 Parser.Lex(); // Eat the '-' token.
3773 isAdd = false;
3774 haveEaten = true;
3775 }
3776 if (Parser.getTok().is(AsmToken::Identifier))
3777 Reg = tryParseRegister();
3778 if (Reg == -1) {
3779 if (!haveEaten)
3780 return MatchOperand_NoMatch;
3781 Error(Parser.getTok().getLoc(), "register expected");
3782 return MatchOperand_ParseFail;
3783 }
3784 SMLoc E = Parser.getTok().getLoc();
3785
3786 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3787 0, S, E));
3788
3789 return MatchOperand_Success;
3790}
3791
Jim Grosbacha77295d2011-09-08 22:07:06 +00003792/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3793/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3794/// when they refer multiple MIOperands inside a single one.
3795bool ARMAsmParser::
3796cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3797 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3798 // Rt, Rt2
3799 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3800 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3801 // Create a writeback register dummy placeholder.
3802 Inst.addOperand(MCOperand::CreateReg(0));
3803 // addr
3804 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3805 // pred
3806 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3807 return true;
3808}
3809
3810/// cvtT2StrdPre - Convert parsed operands to MCInst.
3811/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3812/// when they refer multiple MIOperands inside a single one.
3813bool ARMAsmParser::
3814cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3815 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3816 // Create a writeback register dummy placeholder.
3817 Inst.addOperand(MCOperand::CreateReg(0));
3818 // Rt, Rt2
3819 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3820 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3821 // addr
3822 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3823 // pred
3824 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3825 return true;
3826}
3827
Jim Grosbacheeec0252011-09-08 00:39:19 +00003828/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3829/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3830/// when they refer multiple MIOperands inside a single one.
3831bool ARMAsmParser::
3832cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3833 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3834 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3835
3836 // Create a writeback register dummy placeholder.
3837 Inst.addOperand(MCOperand::CreateImm(0));
3838
3839 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3840 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3841 return true;
3842}
3843
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003844/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3845/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3846/// when they refer multiple MIOperands inside a single one.
3847bool ARMAsmParser::
3848cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3849 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3850 // Create a writeback register dummy placeholder.
3851 Inst.addOperand(MCOperand::CreateImm(0));
3852 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3853 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3854 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3855 return true;
3856}
3857
Jim Grosbach1355cf12011-07-26 17:10:22 +00003858/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003859/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3860/// when they refer multiple MIOperands inside a single one.
3861bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003862cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003863 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3864 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3865
3866 // Create a writeback register dummy placeholder.
3867 Inst.addOperand(MCOperand::CreateImm(0));
3868
Jim Grosbach7ce05792011-08-03 23:50:40 +00003869 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003870 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3871 return true;
3872}
3873
Owen Anderson9ab0f252011-08-26 20:43:14 +00003874/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3875/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3876/// when they refer multiple MIOperands inside a single one.
3877bool ARMAsmParser::
3878cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3879 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3880 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3881
3882 // Create a writeback register dummy placeholder.
3883 Inst.addOperand(MCOperand::CreateImm(0));
3884
3885 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3886 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3887 return true;
3888}
3889
3890
Jim Grosbach548340c2011-08-11 19:22:40 +00003891/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3892/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3893/// when they refer multiple MIOperands inside a single one.
3894bool ARMAsmParser::
3895cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3896 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3897 // Create a writeback register dummy placeholder.
3898 Inst.addOperand(MCOperand::CreateImm(0));
3899 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3900 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3901 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3902 return true;
3903}
3904
Jim Grosbach1355cf12011-07-26 17:10:22 +00003905/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003906/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3907/// when they refer multiple MIOperands inside a single one.
3908bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003909cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003910 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3911 // Create a writeback register dummy placeholder.
3912 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003913 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3914 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3915 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003916 return true;
3917}
3918
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003919/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3920/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3921/// when they refer multiple MIOperands inside a single one.
3922bool ARMAsmParser::
3923cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3924 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3925 // Create a writeback register dummy placeholder.
3926 Inst.addOperand(MCOperand::CreateImm(0));
3927 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3928 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3929 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3930 return true;
3931}
3932
Jim Grosbach7ce05792011-08-03 23:50:40 +00003933/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3934/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3935/// when they refer multiple MIOperands inside a single one.
3936bool ARMAsmParser::
3937cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3938 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3939 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003940 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003941 // Create a writeback register dummy placeholder.
3942 Inst.addOperand(MCOperand::CreateImm(0));
3943 // addr
3944 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3945 // offset
3946 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3947 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003948 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3949 return true;
3950}
3951
Jim Grosbach7ce05792011-08-03 23:50:40 +00003952/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003953/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3954/// when they refer multiple MIOperands inside a single one.
3955bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003956cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3957 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3958 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003959 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003960 // Create a writeback register dummy placeholder.
3961 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003962 // addr
3963 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3964 // offset
3965 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3966 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003967 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3968 return true;
3969}
3970
Jim Grosbach7ce05792011-08-03 23:50:40 +00003971/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003972/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3973/// when they refer multiple MIOperands inside a single one.
3974bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003975cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3976 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003977 // Create a writeback register dummy placeholder.
3978 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003979 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003980 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003981 // addr
3982 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3983 // offset
3984 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3985 // pred
3986 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3987 return true;
3988}
3989
3990/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3991/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3992/// when they refer multiple MIOperands inside a single one.
3993bool ARMAsmParser::
3994cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3995 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3996 // Create a writeback register dummy placeholder.
3997 Inst.addOperand(MCOperand::CreateImm(0));
3998 // Rt
3999 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
4000 // addr
4001 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
4002 // offset
4003 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
4004 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00004005 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4006 return true;
4007}
4008
Jim Grosbach2fd2b872011-08-10 20:29:19 +00004009/// cvtLdrdPre - Convert parsed operands to MCInst.
4010/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4011/// when they refer multiple MIOperands inside a single one.
4012bool ARMAsmParser::
4013cvtLdrdPre(MCInst &Inst, unsigned Opcode,
4014 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4015 // Rt, Rt2
4016 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
4017 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
4018 // Create a writeback register dummy placeholder.
4019 Inst.addOperand(MCOperand::CreateImm(0));
4020 // addr
4021 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
4022 // pred
4023 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4024 return true;
4025}
4026
Jim Grosbach14605d12011-08-11 20:28:23 +00004027/// cvtStrdPre - Convert parsed operands to MCInst.
4028/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4029/// when they refer multiple MIOperands inside a single one.
4030bool ARMAsmParser::
4031cvtStrdPre(MCInst &Inst, unsigned Opcode,
4032 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4033 // Create a writeback register dummy placeholder.
4034 Inst.addOperand(MCOperand::CreateImm(0));
4035 // Rt, Rt2
4036 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
4037 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
4038 // addr
4039 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
4040 // pred
4041 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4042 return true;
4043}
4044
Jim Grosbach623a4542011-08-10 22:42:16 +00004045/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
4046/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4047/// when they refer multiple MIOperands inside a single one.
4048bool ARMAsmParser::
4049cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
4050 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4051 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
4052 // Create a writeback register dummy placeholder.
4053 Inst.addOperand(MCOperand::CreateImm(0));
4054 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
4055 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4056 return true;
4057}
4058
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004059/// cvtThumbMultiple- Convert parsed operands to MCInst.
4060/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4061/// when they refer multiple MIOperands inside a single one.
4062bool ARMAsmParser::
4063cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
4064 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4065 // The second source operand must be the same register as the destination
4066 // operand.
4067 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00004068 (((ARMOperand*)Operands[3])->getReg() !=
4069 ((ARMOperand*)Operands[5])->getReg()) &&
4070 (((ARMOperand*)Operands[3])->getReg() !=
4071 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004072 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00004073 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004074 return false;
4075 }
4076 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
4077 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach1b332862011-11-10 22:10:12 +00004078 // If we have a three-operand form, make sure to set Rn to be the operand
4079 // that isn't the same as Rd.
4080 unsigned RegOp = 4;
4081 if (Operands.size() == 6 &&
4082 ((ARMOperand*)Operands[4])->getReg() ==
4083 ((ARMOperand*)Operands[3])->getReg())
4084 RegOp = 5;
4085 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
4086 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004087 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
4088
4089 return true;
4090}
Jim Grosbach623a4542011-08-10 22:42:16 +00004091
Jim Grosbach12431322011-10-24 22:16:58 +00004092bool ARMAsmParser::
4093cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
4094 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4095 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004096 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00004097 // Create a writeback register dummy placeholder.
4098 Inst.addOperand(MCOperand::CreateImm(0));
4099 // Vn
4100 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4101 // pred
4102 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4103 return true;
4104}
4105
4106bool ARMAsmParser::
4107cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
4108 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4109 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004110 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00004111 // Create a writeback register dummy placeholder.
4112 Inst.addOperand(MCOperand::CreateImm(0));
4113 // Vn
4114 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4115 // Vm
4116 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4117 // pred
4118 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4119 return true;
4120}
4121
Jim Grosbach4334e032011-10-31 21:50:31 +00004122bool ARMAsmParser::
4123cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
4124 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4125 // Create a writeback register dummy placeholder.
4126 Inst.addOperand(MCOperand::CreateImm(0));
4127 // Vn
4128 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4129 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004130 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00004131 // pred
4132 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4133 return true;
4134}
4135
4136bool ARMAsmParser::
4137cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
4138 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4139 // Create a writeback register dummy placeholder.
4140 Inst.addOperand(MCOperand::CreateImm(0));
4141 // Vn
4142 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4143 // Vm
4144 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4145 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004146 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00004147 // pred
4148 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4149 return true;
4150}
4151
Bill Wendlinge7176102010-11-06 22:36:58 +00004152/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004153/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00004154bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00004155parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00004156 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00004157 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00004158 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00004159 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004160 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004161
Sean Callanan18b83232010-01-19 21:44:56 +00004162 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00004163 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00004164 if (BaseRegNum == -1)
4165 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004166
Daniel Dunbar05710932011-01-18 05:34:17 +00004167 // The next token must either be a comma or a closing bracket.
4168 const AsmToken &Tok = Parser.getTok();
4169 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004170 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00004171
Jim Grosbach7ce05792011-08-03 23:50:40 +00004172 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00004173 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004174 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004175
Jim Grosbach7ce05792011-08-03 23:50:40 +00004176 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004177 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00004178
Jim Grosbachfb12f352011-09-19 18:42:21 +00004179 // If there's a pre-indexing writeback marker, '!', just add it as a token
4180 // operand. It's rather odd, but syntactically valid.
4181 if (Parser.getTok().is(AsmToken::Exclaim)) {
4182 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4183 Parser.Lex(); // Eat the '!'.
4184 }
4185
Jim Grosbach7ce05792011-08-03 23:50:40 +00004186 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004187 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004188
Jim Grosbach7ce05792011-08-03 23:50:40 +00004189 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
4190 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004191
Jim Grosbach57dcb852011-10-11 17:29:55 +00004192 // If we have a ':', it's an alignment specifier.
4193 if (Parser.getTok().is(AsmToken::Colon)) {
4194 Parser.Lex(); // Eat the ':'.
4195 E = Parser.getTok().getLoc();
4196
4197 const MCExpr *Expr;
4198 if (getParser().ParseExpression(Expr))
4199 return true;
4200
4201 // The expression has to be a constant. Memory references with relocations
4202 // don't come through here, as they use the <label> forms of the relevant
4203 // instructions.
4204 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4205 if (!CE)
4206 return Error (E, "constant expression expected");
4207
4208 unsigned Align = 0;
4209 switch (CE->getValue()) {
4210 default:
Jim Grosbacheeaf1c12011-12-19 18:31:43 +00004211 return Error(E,
4212 "alignment specifier must be 16, 32, 64, 128, or 256 bits");
4213 case 16: Align = 2; break;
4214 case 32: Align = 4; break;
Jim Grosbach57dcb852011-10-11 17:29:55 +00004215 case 64: Align = 8; break;
4216 case 128: Align = 16; break;
4217 case 256: Align = 32; break;
4218 }
4219
4220 // Now we should have the closing ']'
4221 E = Parser.getTok().getLoc();
4222 if (Parser.getTok().isNot(AsmToken::RBrac))
4223 return Error(E, "']' expected");
4224 Parser.Lex(); // Eat right bracket token.
4225
4226 // Don't worry about range checking the value here. That's handled by
4227 // the is*() predicates.
4228 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
4229 ARM_AM::no_shift, 0, Align,
4230 false, S, E));
4231
4232 // If there's a pre-indexing writeback marker, '!', just add it as a token
4233 // operand.
4234 if (Parser.getTok().is(AsmToken::Exclaim)) {
4235 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4236 Parser.Lex(); // Eat the '!'.
4237 }
4238
4239 return false;
4240 }
4241
4242 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004243 // offset. Be friendly and also accept a plain integer (without a leading
4244 // hash) for gas compatibility.
4245 if (Parser.getTok().is(AsmToken::Hash) ||
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004246 Parser.getTok().is(AsmToken::Dollar) ||
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004247 Parser.getTok().is(AsmToken::Integer)) {
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004248 if (Parser.getTok().isNot(AsmToken::Integer))
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004249 Parser.Lex(); // Eat the '#'.
Jim Grosbach7ce05792011-08-03 23:50:40 +00004250 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004251
Owen Anderson0da10cf2011-08-29 19:36:44 +00004252 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00004253 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004254 if (getParser().ParseExpression(Offset))
4255 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004256
4257 // The expression has to be a constant. Memory references with relocations
4258 // don't come through here, as they use the <label> forms of the relevant
4259 // instructions.
4260 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
4261 if (!CE)
4262 return Error (E, "constant expression expected");
4263
Owen Anderson0da10cf2011-08-29 19:36:44 +00004264 // If the constant was #-0, represent it as INT32_MIN.
4265 int32_t Val = CE->getValue();
4266 if (isNegative && Val == 0)
4267 CE = MCConstantExpr::Create(INT32_MIN, getContext());
4268
Jim Grosbach7ce05792011-08-03 23:50:40 +00004269 // Now we should have the closing ']'
4270 E = Parser.getTok().getLoc();
4271 if (Parser.getTok().isNot(AsmToken::RBrac))
4272 return Error(E, "']' expected");
4273 Parser.Lex(); // Eat right bracket token.
4274
4275 // Don't worry about range checking the value here. That's handled by
4276 // the is*() predicates.
4277 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004278 ARM_AM::no_shift, 0, 0,
4279 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00004280
4281 // If there's a pre-indexing writeback marker, '!', just add it as a token
4282 // operand.
4283 if (Parser.getTok().is(AsmToken::Exclaim)) {
4284 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4285 Parser.Lex(); // Eat the '!'.
4286 }
4287
4288 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004289 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004290
4291 // The register offset is optionally preceded by a '+' or '-'
4292 bool isNegative = false;
4293 if (Parser.getTok().is(AsmToken::Minus)) {
4294 isNegative = true;
4295 Parser.Lex(); // Eat the '-'.
4296 } else if (Parser.getTok().is(AsmToken::Plus)) {
4297 // Nothing to do.
4298 Parser.Lex(); // Eat the '+'.
4299 }
4300
4301 E = Parser.getTok().getLoc();
4302 int OffsetRegNum = tryParseRegister();
4303 if (OffsetRegNum == -1)
4304 return Error(E, "register expected");
4305
4306 // If there's a shift operator, handle it.
4307 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004308 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004309 if (Parser.getTok().is(AsmToken::Comma)) {
4310 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004311 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004312 return true;
4313 }
4314
4315 // Now we should have the closing ']'
4316 E = Parser.getTok().getLoc();
4317 if (Parser.getTok().isNot(AsmToken::RBrac))
4318 return Error(E, "']' expected");
4319 Parser.Lex(); // Eat right bracket token.
4320
4321 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004322 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00004323 S, E));
4324
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00004325 // If there's a pre-indexing writeback marker, '!', just add it as a token
4326 // operand.
4327 if (Parser.getTok().is(AsmToken::Exclaim)) {
4328 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4329 Parser.Lex(); // Eat the '!'.
4330 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004331
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004332 return false;
4333}
4334
Jim Grosbach7ce05792011-08-03 23:50:40 +00004335/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004336/// ( lsl | lsr | asr | ror ) , # shift_amount
4337/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00004338/// return true if it parses a shift otherwise it returns false.
4339bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
4340 unsigned &Amount) {
4341 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00004342 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004343 if (Tok.isNot(AsmToken::Identifier))
4344 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00004345 StringRef ShiftName = Tok.getString();
Jim Grosbachaf4edea2011-12-07 23:40:58 +00004346 if (ShiftName == "lsl" || ShiftName == "LSL" ||
4347 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson00828302011-03-18 22:50:18 +00004348 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004349 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00004350 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004351 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00004352 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004353 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00004354 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004355 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00004356 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004357 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00004358 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00004359 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004360
Jim Grosbach7ce05792011-08-03 23:50:40 +00004361 // rrx stands alone.
4362 Amount = 0;
4363 if (St != ARM_AM::rrx) {
4364 Loc = Parser.getTok().getLoc();
4365 // A '#' and a shift amount.
4366 const AsmToken &HashTok = Parser.getTok();
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004367 if (HashTok.isNot(AsmToken::Hash) &&
4368 HashTok.isNot(AsmToken::Dollar))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004369 return Error(HashTok.getLoc(), "'#' expected");
4370 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004371
Jim Grosbach7ce05792011-08-03 23:50:40 +00004372 const MCExpr *Expr;
4373 if (getParser().ParseExpression(Expr))
4374 return true;
4375 // Range check the immediate.
4376 // lsl, ror: 0 <= imm <= 31
4377 // lsr, asr: 0 <= imm <= 32
4378 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4379 if (!CE)
4380 return Error(Loc, "shift amount must be an immediate");
4381 int64_t Imm = CE->getValue();
4382 if (Imm < 0 ||
4383 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4384 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4385 return Error(Loc, "immediate shift value out of range");
4386 Amount = Imm;
4387 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004388
4389 return false;
4390}
4391
Jim Grosbach9d390362011-10-03 23:38:36 +00004392/// parseFPImm - A floating point immediate expression operand.
4393ARMAsmParser::OperandMatchResultTy ARMAsmParser::
4394parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach51222d12012-01-20 18:09:51 +00004395 // Anything that can accept a floating point constant as an operand
4396 // needs to go through here, as the regular ParseExpression is
4397 // integer only.
4398 //
4399 // This routine still creates a generic Immediate operand, containing
4400 // a bitcast of the 64-bit floating point value. The various operands
4401 // that accept floats can check whether the value is valid for them
4402 // via the standard is*() predicates.
4403
Jim Grosbach9d390362011-10-03 23:38:36 +00004404 SMLoc S = Parser.getTok().getLoc();
4405
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004406 if (Parser.getTok().isNot(AsmToken::Hash) &&
4407 Parser.getTok().isNot(AsmToken::Dollar))
Jim Grosbach9d390362011-10-03 23:38:36 +00004408 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00004409
4410 // Disambiguate the VMOV forms that can accept an FP immediate.
4411 // vmov.f32 <sreg>, #imm
4412 // vmov.f64 <dreg>, #imm
4413 // vmov.f32 <dreg>, #imm @ vector f32x2
4414 // vmov.f32 <qreg>, #imm @ vector f32x4
4415 //
4416 // There are also the NEON VMOV instructions which expect an
4417 // integer constant. Make sure we don't try to parse an FPImm
4418 // for these:
4419 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4420 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4421 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4422 TyOp->getToken() != ".f64"))
4423 return MatchOperand_NoMatch;
4424
Jim Grosbach9d390362011-10-03 23:38:36 +00004425 Parser.Lex(); // Eat the '#'.
4426
4427 // Handle negation, as that still comes through as a separate token.
4428 bool isNegative = false;
4429 if (Parser.getTok().is(AsmToken::Minus)) {
4430 isNegative = true;
4431 Parser.Lex();
4432 }
4433 const AsmToken &Tok = Parser.getTok();
Jim Grosbachae69f702012-01-19 02:47:30 +00004434 SMLoc Loc = Tok.getLoc();
Jim Grosbach9d390362011-10-03 23:38:36 +00004435 if (Tok.is(AsmToken::Real)) {
Jim Grosbach51222d12012-01-20 18:09:51 +00004436 APFloat RealVal(APFloat::IEEEsingle, Tok.getString());
Jim Grosbach9d390362011-10-03 23:38:36 +00004437 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4438 // If we had a '-' in front, toggle the sign bit.
Jim Grosbach51222d12012-01-20 18:09:51 +00004439 IntVal ^= (uint64_t)isNegative << 31;
Jim Grosbach9d390362011-10-03 23:38:36 +00004440 Parser.Lex(); // Eat the token.
Jim Grosbach51222d12012-01-20 18:09:51 +00004441 Operands.push_back(ARMOperand::CreateImm(
4442 MCConstantExpr::Create(IntVal, getContext()),
4443 S, Parser.getTok().getLoc()));
Jim Grosbach9d390362011-10-03 23:38:36 +00004444 return MatchOperand_Success;
4445 }
Jim Grosbach51222d12012-01-20 18:09:51 +00004446 // Also handle plain integers. Instructions which allow floating point
4447 // immediates also allow a raw encoded 8-bit value.
Jim Grosbach9d390362011-10-03 23:38:36 +00004448 if (Tok.is(AsmToken::Integer)) {
4449 int64_t Val = Tok.getIntVal();
4450 Parser.Lex(); // Eat the token.
4451 if (Val > 255 || Val < 0) {
Jim Grosbachae69f702012-01-19 02:47:30 +00004452 Error(Loc, "encoded floating point value out of range");
Jim Grosbach9d390362011-10-03 23:38:36 +00004453 return MatchOperand_ParseFail;
4454 }
Jim Grosbach51222d12012-01-20 18:09:51 +00004455 double RealVal = ARM_AM::getFPImmFloat(Val);
4456 Val = APFloat(APFloat::IEEEdouble, RealVal).bitcastToAPInt().getZExtValue();
4457 Operands.push_back(ARMOperand::CreateImm(
4458 MCConstantExpr::Create(Val, getContext()), S,
4459 Parser.getTok().getLoc()));
Jim Grosbach9d390362011-10-03 23:38:36 +00004460 return MatchOperand_Success;
4461 }
4462
Jim Grosbachae69f702012-01-19 02:47:30 +00004463 Error(Loc, "invalid floating point immediate");
Jim Grosbach9d390362011-10-03 23:38:36 +00004464 return MatchOperand_ParseFail;
4465}
Jim Grosbach51222d12012-01-20 18:09:51 +00004466
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004467/// Parse a arm instruction operand. For now this parses the operand regardless
4468/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004469bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004470 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00004471 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004472
4473 // Check if the current operand has a custom associated parser, if so, try to
4474 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00004475 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4476 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004477 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00004478 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4479 // there was a match, but an error occurred, in which case, just return that
4480 // the operand parsing failed.
4481 if (ResTy == MatchOperand_ParseFail)
4482 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004483
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004484 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00004485 default:
4486 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00004487 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00004488 case AsmToken::Identifier: {
Jim Grosbach1355cf12011-07-26 17:10:22 +00004489 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00004490 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00004491 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00004492 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00004493 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00004494 else if (Res == -1) // irrecoverable error
4495 return true;
Jim Grosbach3cbe43f2011-12-20 22:26:38 +00004496 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbachb84ad4a2012-03-15 21:34:14 +00004497 if (Mnemonic == "vmrs" &&
4498 Parser.getTok().getString().equals_lower("apsr_nzcv")) {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004499 S = Parser.getTok().getLoc();
4500 Parser.Lex();
Jim Grosbachb84ad4a2012-03-15 21:34:14 +00004501 Operands.push_back(ARMOperand::CreateToken("APSR_nzcv", S));
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004502 return false;
4503 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00004504
4505 // Fall though for the Identifier case that is not a register or a
4506 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00004507 }
Jim Grosbach758a5192011-10-26 21:14:08 +00004508 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00004509 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00004510 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00004511 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00004512 // This was not a register so parse other operands that start with an
4513 // identifier (like labels) as expressions and create them as immediates.
4514 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00004515 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00004516 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004517 return true;
Sean Callanan76264762010-04-02 22:27:05 +00004518 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004519 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4520 return false;
4521 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004522 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004523 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00004524 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004525 return parseRegisterList(Operands);
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004526 case AsmToken::Dollar:
Owen Anderson63553c72011-08-29 17:17:09 +00004527 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00004528 // #42 -> immediate.
4529 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00004530 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004531 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00004532 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00004533 const MCExpr *ImmVal;
4534 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004535 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00004536 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbached6a0c52011-11-01 22:37:37 +00004537 if (CE) {
4538 int32_t Val = CE->getValue();
4539 if (isNegative && Val == 0)
4540 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Anderson63553c72011-08-29 17:17:09 +00004541 }
Sean Callanan76264762010-04-02 22:27:05 +00004542 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004543 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4544 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00004545 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004546 case AsmToken::Colon: {
4547 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00004548 // FIXME: Check it's an expression prefix,
4549 // e.g. (FOO - :lower16:BAR) isn't legal.
4550 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004551 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004552 return true;
4553
Evan Cheng75972122011-01-13 07:58:56 +00004554 const MCExpr *SubExprVal;
4555 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004556 return true;
4557
Evan Cheng75972122011-01-13 07:58:56 +00004558 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4559 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00004560 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00004561 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00004562 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004563 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004564 }
4565}
4566
Jim Grosbach1355cf12011-07-26 17:10:22 +00004567// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00004568// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004569bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00004570 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004571
4572 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00004573 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00004574 Parser.Lex(); // Eat ':'
4575
4576 if (getLexer().isNot(AsmToken::Identifier)) {
4577 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4578 return true;
4579 }
4580
4581 StringRef IDVal = Parser.getTok().getIdentifier();
4582 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00004583 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004584 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00004585 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004586 } else {
4587 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4588 return true;
4589 }
4590 Parser.Lex();
4591
4592 if (getLexer().isNot(AsmToken::Colon)) {
4593 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4594 return true;
4595 }
4596 Parser.Lex(); // Eat the last ':'
4597 return false;
4598}
4599
Daniel Dunbar352e1482011-01-11 15:59:50 +00004600/// \brief Given a mnemonic, split out possible predication code and carry
4601/// setting letters to form a canonical mnemonic and flags.
4602//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004603// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00004604// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004605StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00004606 unsigned &PredicationCode,
4607 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004608 unsigned &ProcessorIMod,
4609 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004610 PredicationCode = ARMCC::AL;
4611 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004612 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004613
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004614 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00004615 //
4616 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00004617 if ((Mnemonic == "movs" && isThumb()) ||
4618 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4619 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4620 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4621 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4622 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4623 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
Jim Grosbach68490192011-12-19 19:43:50 +00004624 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" ||
4625 Mnemonic == "fmuls")
Daniel Dunbar352e1482011-01-11 15:59:50 +00004626 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00004627
Jim Grosbach3f00e312011-07-11 17:09:57 +00004628 // First, split out any predication code. Ignore mnemonics we know aren't
4629 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00004630 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00004631 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00004632 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00004633 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00004634 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4635 .Case("eq", ARMCC::EQ)
4636 .Case("ne", ARMCC::NE)
4637 .Case("hs", ARMCC::HS)
4638 .Case("cs", ARMCC::HS)
4639 .Case("lo", ARMCC::LO)
4640 .Case("cc", ARMCC::LO)
4641 .Case("mi", ARMCC::MI)
4642 .Case("pl", ARMCC::PL)
4643 .Case("vs", ARMCC::VS)
4644 .Case("vc", ARMCC::VC)
4645 .Case("hi", ARMCC::HI)
4646 .Case("ls", ARMCC::LS)
4647 .Case("ge", ARMCC::GE)
4648 .Case("lt", ARMCC::LT)
4649 .Case("gt", ARMCC::GT)
4650 .Case("le", ARMCC::LE)
4651 .Case("al", ARMCC::AL)
4652 .Default(~0U);
4653 if (CC != ~0U) {
4654 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4655 PredicationCode = CC;
4656 }
Bill Wendling52925b62010-10-29 23:50:21 +00004657 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004658
Daniel Dunbar352e1482011-01-11 15:59:50 +00004659 // Next, determine if we have a carry setting bit. We explicitly ignore all
4660 // the instructions we know end in 's'.
4661 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00004662 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00004663 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4664 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4665 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach67ca1ad2011-12-08 00:49:29 +00004666 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach48171e72011-12-10 00:01:02 +00004667 Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
Jim Grosbach9c397892011-12-19 19:02:41 +00004668 Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" ||
Jim Grosbach6357cae2012-03-15 20:48:18 +00004669 Mnemonic == "fmuls" || Mnemonic == "fcmps" || Mnemonic == "fcmpzs" ||
Evan Cheng82509e52012-04-11 00:13:00 +00004670 Mnemonic == "vfms" || Mnemonic == "vfnms" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00004671 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004672 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4673 CarrySetting = true;
4674 }
4675
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004676 // The "cps" instruction can have a interrupt mode operand which is glued into
4677 // the mnemonic. Check if this is the case, split it and parse the imod op
4678 if (Mnemonic.startswith("cps")) {
4679 // Split out any imod code.
4680 unsigned IMod =
4681 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4682 .Case("ie", ARM_PROC::IE)
4683 .Case("id", ARM_PROC::ID)
4684 .Default(~0U);
4685 if (IMod != ~0U) {
4686 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4687 ProcessorIMod = IMod;
4688 }
4689 }
4690
Jim Grosbach89df9962011-08-26 21:43:41 +00004691 // The "it" instruction has the condition mask on the end of the mnemonic.
4692 if (Mnemonic.startswith("it")) {
4693 ITMask = Mnemonic.slice(2, Mnemonic.size());
4694 Mnemonic = Mnemonic.slice(0, 2);
4695 }
4696
Daniel Dunbar352e1482011-01-11 15:59:50 +00004697 return Mnemonic;
4698}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004699
4700/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4701/// inclusion of carry set or predication code operands.
4702//
4703// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004704void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00004705getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004706 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004707 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4708 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004709 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004710 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004711 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004712 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004713 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Evan Cheng82509e52012-04-11 00:13:00 +00004714 Mnemonic == "vfm" || Mnemonic == "vfnm" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004715 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004716 Mnemonic == "mla" || Mnemonic == "smlal" ||
4717 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004718 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004719 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004720 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004721
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004722 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4723 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4724 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4725 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004726 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4727 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004728 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004729 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4730 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4731 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004732 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4733 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004734 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004735 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004736 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004737 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004738
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004739 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004740 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004741 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004742 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004743 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004744}
4745
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004746bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4747 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004748 // FIXME: This is all horribly hacky. We really need a better way to deal
4749 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004750
4751 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4752 // another does not. Specifically, the MOVW instruction does not. So we
4753 // special case it here and remove the defaulted (non-setting) cc_out
4754 // operand if that's the instruction we're trying to match.
4755 //
4756 // We do this as post-processing of the explicit operands rather than just
4757 // conditionally adding the cc_out in the first place because we need
4758 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004759 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004760 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4761 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4762 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4763 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004764
4765 // Register-register 'add' for thumb does not have a cc_out operand
4766 // when there are only two register operands.
4767 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4768 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4769 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4770 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4771 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004772 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004773 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4774 // have to check the immediate range here since Thumb2 has a variant
4775 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004776 if (((isThumb() && Mnemonic == "add") ||
4777 (isThumbTwo() && Mnemonic == "sub")) &&
4778 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004779 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4780 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4781 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004782 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
Jim Grosbacha23ecc22012-04-10 17:31:55 +00004783 ((Mnemonic == "add" &&static_cast<ARMOperand*>(Operands[5])->isReg()) ||
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004784 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004785 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004786 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4787 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004788 // selecting via the generic "add" mnemonic, so to know that we
4789 // should remove the cc_out operand, we have to explicitly check that
4790 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004791 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4792 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004793 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4794 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4795 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4796 // Nest conditions rather than one big 'if' statement for readability.
4797 //
4798 // If either register is a high reg, it's either one of the SP
4799 // variants (handled above) or a 32-bit encoding, so we just
Jim Grosbach12a88632012-01-21 00:07:56 +00004800 // check against T3. If the second register is the PC, this is an
4801 // alternate form of ADR, which uses encoding T4, so check for that too.
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004802 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4803 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
Jim Grosbach12a88632012-01-21 00:07:56 +00004804 static_cast<ARMOperand*>(Operands[4])->getReg() != ARM::PC &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004805 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4806 return false;
4807 // If both registers are low, we're in an IT block, and the immediate is
4808 // in range, we should use encoding T1 instead, which has a cc_out.
4809 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004810 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004811 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4812 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4813 return false;
4814
4815 // Otherwise, we use encoding T4, which does not have a cc_out
4816 // operand.
4817 return true;
4818 }
4819
Jim Grosbach64944f42011-09-14 21:00:40 +00004820 // The thumb2 multiply instruction doesn't have a CCOut register, so
4821 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4822 // use the 16-bit encoding or not.
4823 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4824 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4825 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4826 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4827 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4828 // If the registers aren't low regs, the destination reg isn't the
4829 // same as one of the source regs, or the cc_out operand is zero
4830 // outside of an IT block, we have to use the 32-bit encoding, so
4831 // remove the cc_out operand.
4832 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4833 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach1de0bd12011-11-15 19:29:45 +00004834 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach64944f42011-09-14 21:00:40 +00004835 !inITBlock() ||
4836 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4837 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4838 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4839 static_cast<ARMOperand*>(Operands[4])->getReg())))
4840 return true;
4841
Jim Grosbach7f1ec952011-11-15 19:55:16 +00004842 // Also check the 'mul' syntax variant that doesn't specify an explicit
4843 // destination register.
4844 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4845 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4846 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4847 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4848 // If the registers aren't low regs or the cc_out operand is zero
4849 // outside of an IT block, we have to use the 32-bit encoding, so
4850 // remove the cc_out operand.
4851 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4852 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4853 !inITBlock()))
4854 return true;
4855
Jim Grosbach64944f42011-09-14 21:00:40 +00004856
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004857
Jim Grosbachf69c8042011-08-24 21:42:27 +00004858 // Register-register 'add/sub' for thumb does not have a cc_out operand
4859 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4860 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4861 // right, this will result in better diagnostics (which operand is off)
4862 // anyway.
4863 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4864 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004865 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4866 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
Jim Grosbacha23ecc22012-04-10 17:31:55 +00004867 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4868 (static_cast<ARMOperand*>(Operands[4])->isImm() ||
4869 (Operands.size() == 6 &&
4870 static_cast<ARMOperand*>(Operands[5])->isImm())))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004871 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004872
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004873 return false;
4874}
4875
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004876static bool isDataTypeToken(StringRef Tok) {
4877 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4878 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4879 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4880 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4881 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4882 Tok == ".f" || Tok == ".d";
4883}
4884
4885// FIXME: This bit should probably be handled via an explicit match class
4886// in the .td files that matches the suffix instead of having it be
4887// a literal string token the way it is now.
4888static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4889 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4890}
4891
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004892static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004893/// Parse an arm instruction mnemonic followed by its operands.
4894bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4895 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004896 // Apply mnemonic aliases before doing anything else, as the destination
4897 // mnemnonic may include suffices and we want to handle them normally.
4898 // The generic tblgen'erated code does this later, at the start of
4899 // MatchInstructionImpl(), but that's too late for aliases that include
4900 // any sort of suffix.
4901 unsigned AvailableFeatures = getAvailableFeatures();
4902 applyMnemonicAliases(Name, AvailableFeatures);
4903
Jim Grosbacha39cda72011-12-14 02:16:11 +00004904 // First check for the ARM-specific .req directive.
4905 if (Parser.getTok().is(AsmToken::Identifier) &&
4906 Parser.getTok().getIdentifier() == ".req") {
4907 parseDirectiveReq(Name, NameLoc);
4908 // We always return 'error' for this, as we're done with this
4909 // statement and don't need to match the 'instruction."
4910 return true;
4911 }
4912
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004913 // Create the leading tokens for the mnemonic, split by '.' characters.
4914 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004915 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004916
Daniel Dunbar352e1482011-01-11 15:59:50 +00004917 // Split out the predication code and carry setting flag from the mnemonic.
4918 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004919 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004920 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004921 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004922 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004923 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004924
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004925 // In Thumb1, only the branch (B) instruction can be predicated.
4926 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4927 Parser.EatToEndOfStatement();
4928 return Error(NameLoc, "conditional execution not supported in Thumb1");
4929 }
4930
Jim Grosbachffa32252011-07-19 19:13:28 +00004931 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4932
Jim Grosbach89df9962011-08-26 21:43:41 +00004933 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4934 // is the mask as it will be for the IT encoding if the conditional
4935 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4936 // where the conditional bit0 is zero, the instruction post-processing
4937 // will adjust the mask accordingly.
4938 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004939 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4940 if (ITMask.size() > 3) {
4941 Parser.EatToEndOfStatement();
4942 return Error(Loc, "too many conditions on IT instruction");
4943 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004944 unsigned Mask = 8;
4945 for (unsigned i = ITMask.size(); i != 0; --i) {
4946 char pos = ITMask[i - 1];
4947 if (pos != 't' && pos != 'e') {
4948 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004949 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004950 }
4951 Mask >>= 1;
4952 if (ITMask[i - 1] == 't')
4953 Mask |= 8;
4954 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004955 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004956 }
4957
Jim Grosbachffa32252011-07-19 19:13:28 +00004958 // FIXME: This is all a pretty gross hack. We should automatically handle
4959 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004960
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004961 // Next, add the CCOut and ConditionCode operands, if needed.
4962 //
4963 // For mnemonics which can ever incorporate a carry setting bit or predication
4964 // code, our matching model involves us always generating CCOut and
4965 // ConditionCode operands to match the mnemonic "as written" and then we let
4966 // the matcher deal with finding the right instruction or generating an
4967 // appropriate error.
4968 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004969 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004970
Jim Grosbach33c16a22011-07-14 22:04:21 +00004971 // If we had a carry-set on an instruction that can't do that, issue an
4972 // error.
4973 if (!CanAcceptCarrySet && CarrySetting) {
4974 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004975 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004976 "' can not set flags, but 's' suffix specified");
4977 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004978 // If we had a predication code on an instruction that can't do that, issue an
4979 // error.
4980 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4981 Parser.EatToEndOfStatement();
4982 return Error(NameLoc, "instruction '" + Mnemonic +
4983 "' is not predicable, but condition code specified");
4984 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004985
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004986 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004987 if (CanAcceptCarrySet) {
4988 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004989 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004990 Loc));
4991 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004992
4993 // Add the predication code operand, if necessary.
4994 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004995 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4996 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004997 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004998 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004999 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00005000
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00005001 // Add the processor imod operand, if necessary.
5002 if (ProcessorIMod) {
5003 Operands.push_back(ARMOperand::CreateImm(
5004 MCConstantExpr::Create(ProcessorIMod, getContext()),
5005 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00005006 }
5007
Daniel Dunbar345a9a62010-08-11 06:37:20 +00005008 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00005009 while (Next != StringRef::npos) {
5010 Start = Next;
5011 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00005012 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00005013
Jim Grosbach7aef99b2011-11-11 23:08:10 +00005014 // Some NEON instructions have an optional datatype suffix that is
5015 // completely ignored. Check for that.
5016 if (isDataTypeToken(ExtraToken) &&
5017 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
5018 continue;
5019
Jim Grosbach81d2e392011-09-07 16:06:04 +00005020 if (ExtraToken != ".n") {
5021 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
5022 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
5023 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00005024 }
5025
5026 // Read the remaining operands.
5027 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00005028 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00005029 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00005030 Parser.EatToEndOfStatement();
5031 return true;
5032 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00005033
5034 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00005035 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00005036
5037 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00005038 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00005039 Parser.EatToEndOfStatement();
5040 return true;
5041 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00005042 }
5043 }
Jim Grosbach16c74252010-10-29 14:46:02 +00005044
Chris Lattnercbf8a982010-09-11 16:18:25 +00005045 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00005046 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00005047 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00005048 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00005049 }
Bill Wendling146018f2010-11-06 21:42:12 +00005050
Chris Lattner34e53142010-09-08 05:10:46 +00005051 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00005052
Jim Grosbachd54b4e62011-08-16 21:12:37 +00005053 // Some instructions, mostly Thumb, have forms for the same mnemonic that
5054 // do and don't have a cc_out optional-def operand. With some spot-checks
5055 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00005056 // parse and adjust accordingly before actually matching. We shouldn't ever
5057 // try to remove a cc_out operand that was explicitly set on the the
5058 // mnemonic, of course (CarrySetting == true). Reason number #317 the
5059 // table driven matcher doesn't fit well with the ARM instruction set.
5060 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00005061 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
5062 Operands.erase(Operands.begin() + 1);
5063 delete Op;
5064 }
5065
Jim Grosbachcf121c32011-07-28 21:57:55 +00005066 // ARM mode 'blx' need special handling, as the register operand version
5067 // is predicable, but the label operand version is not. So, we can't rely
5068 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00005069 // a k_CondCode operand in the list. If we're trying to match the label
5070 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00005071 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
5072 static_cast<ARMOperand*>(Operands[2])->isImm()) {
5073 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
5074 Operands.erase(Operands.begin() + 1);
5075 delete Op;
5076 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00005077
5078 // The vector-compare-to-zero instructions have a literal token "#0" at
5079 // the end that comes to here as an immediate operand. Convert it to a
5080 // token to play nicely with the matcher.
5081 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
5082 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
5083 static_cast<ARMOperand*>(Operands[5])->isImm()) {
5084 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
5085 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
5086 if (CE && CE->getValue() == 0) {
5087 Operands.erase(Operands.begin() + 5);
5088 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5089 delete Op;
5090 }
5091 }
Jim Grosbach68259142011-10-03 22:30:24 +00005092 // VCMP{E} does the same thing, but with a different operand count.
5093 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
5094 static_cast<ARMOperand*>(Operands[4])->isImm()) {
5095 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
5096 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
5097 if (CE && CE->getValue() == 0) {
5098 Operands.erase(Operands.begin() + 4);
5099 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5100 delete Op;
5101 }
5102 }
Jim Grosbach934755a2011-08-22 23:47:13 +00005103 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
Jim Grosbach55b02f22011-12-13 20:50:38 +00005104 // end. Convert it to a token here. Take care not to convert those
5105 // that should hit the Thumb2 encoding.
Jim Grosbach934755a2011-08-22 23:47:13 +00005106 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
Jim Grosbach55b02f22011-12-13 20:50:38 +00005107 static_cast<ARMOperand*>(Operands[3])->isReg() &&
5108 static_cast<ARMOperand*>(Operands[4])->isReg() &&
Jim Grosbach934755a2011-08-22 23:47:13 +00005109 static_cast<ARMOperand*>(Operands[5])->isImm()) {
5110 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
5111 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
Jim Grosbach55b02f22011-12-13 20:50:38 +00005112 if (CE && CE->getValue() == 0 &&
5113 (isThumbOne() ||
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00005114 // The cc_out operand matches the IT block.
5115 ((inITBlock() != CarrySetting) &&
5116 // Neither register operand is a high register.
Jim Grosbach55b02f22011-12-13 20:50:38 +00005117 (isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00005118 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()))))){
Jim Grosbach934755a2011-08-22 23:47:13 +00005119 Operands.erase(Operands.begin() + 5);
5120 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5121 delete Op;
5122 }
5123 }
5124
Chris Lattner98986712010-01-14 22:21:20 +00005125 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005126}
5127
Jim Grosbach189610f2011-07-26 18:25:39 +00005128// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00005129
5130// return 'true' if register list contains non-low GPR registers,
5131// 'false' otherwise. If Reg is in the register list or is HiReg, set
5132// 'containsReg' to true.
5133static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
5134 unsigned HiReg, bool &containsReg) {
5135 containsReg = false;
5136 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5137 unsigned OpReg = Inst.getOperand(i).getReg();
5138 if (OpReg == Reg)
5139 containsReg = true;
5140 // Anything other than a low register isn't legal here.
5141 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
5142 return true;
5143 }
5144 return false;
5145}
5146
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005147// Check if the specified regisgter is in the register list of the inst,
5148// starting at the indicated operand number.
5149static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
5150 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5151 unsigned OpReg = Inst.getOperand(i).getReg();
5152 if (OpReg == Reg)
5153 return true;
5154 }
5155 return false;
5156}
5157
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005158// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
5159// the ARMInsts array) instead. Getting that here requires awkward
5160// API changes, though. Better way?
5161namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005162extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005163}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005164static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005165 return ARMInsts[Opcode];
5166}
5167
Jim Grosbach189610f2011-07-26 18:25:39 +00005168// FIXME: We would really like to be able to tablegen'erate this.
5169bool ARMAsmParser::
5170validateInstruction(MCInst &Inst,
5171 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005172 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005173 SMLoc Loc = Operands[0]->getStartLoc();
5174 // Check the IT block state first.
Jim Grosbach74423e32012-01-25 19:52:01 +00005175 // NOTE: BKPT instruction has the interesting property of being
5176 // allowed in IT blocks, but not being predicable. It just always
Owen Andersonb6b7f512011-09-13 17:59:19 +00005177 // executes.
Jim Grosbach74423e32012-01-25 19:52:01 +00005178 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT &&
5179 Inst.getOpcode() != ARM::BKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005180 unsigned bit = 1;
5181 if (ITState.FirstCond)
5182 ITState.FirstCond = false;
5183 else
Jim Grosbacha1109882011-09-02 23:22:08 +00005184 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005185 // The instruction must be predicable.
5186 if (!MCID.isPredicable())
5187 return Error(Loc, "instructions in IT block must be predicable");
5188 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
5189 unsigned ITCond = bit ? ITState.Cond :
5190 ARMCC::getOppositeCondition(ITState.Cond);
5191 if (Cond != ITCond) {
5192 // Find the condition code Operand to get its SMLoc information.
5193 SMLoc CondLoc;
5194 for (unsigned i = 1; i < Operands.size(); ++i)
5195 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
5196 CondLoc = Operands[i]->getStartLoc();
5197 return Error(CondLoc, "incorrect condition in IT block; got '" +
5198 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
5199 "', but expected '" +
5200 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
5201 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00005202 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005203 } else if (isThumbTwo() && MCID.isPredicable() &&
5204 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005205 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
5206 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005207 return Error(Loc, "predicated instructions must be in IT block");
5208
Jim Grosbach189610f2011-07-26 18:25:39 +00005209 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00005210 case ARM::LDRD:
5211 case ARM::LDRD_PRE:
5212 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005213 case ARM::LDREXD: {
5214 // Rt2 must be Rt + 1.
5215 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5216 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5217 if (Rt2 != Rt + 1)
5218 return Error(Operands[3]->getStartLoc(),
5219 "destination operands must be sequential");
5220 return false;
5221 }
Jim Grosbach14605d12011-08-11 20:28:23 +00005222 case ARM::STRD: {
5223 // Rt2 must be Rt + 1.
5224 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5225 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5226 if (Rt2 != Rt + 1)
5227 return Error(Operands[3]->getStartLoc(),
5228 "source operands must be sequential");
5229 return false;
5230 }
Jim Grosbach53642c52011-08-10 20:49:18 +00005231 case ARM::STRD_PRE:
5232 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005233 case ARM::STREXD: {
5234 // Rt2 must be Rt + 1.
5235 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5236 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
5237 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00005238 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00005239 "source operands must be sequential");
5240 return false;
5241 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005242 case ARM::SBFX:
5243 case ARM::UBFX: {
5244 // width must be in range [1, 32-lsb]
5245 unsigned lsb = Inst.getOperand(2).getImm();
5246 unsigned widthm1 = Inst.getOperand(3).getImm();
5247 if (widthm1 >= 32 - lsb)
5248 return Error(Operands[5]->getStartLoc(),
5249 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00005250 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005251 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005252 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005253 // If we're parsing Thumb2, the .w variant is available and handles
5254 // most cases that are normally illegal for a Thumb1 LDM
5255 // instruction. We'll make the transformation in processInstruction()
5256 // if necessary.
5257 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005258 // Thumb LDM instructions are writeback iff the base register is not
5259 // in the register list.
5260 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005261 bool hasWritebackToken =
5262 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5263 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00005264 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005265 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005266 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
5267 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005268 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005269 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005270 return Error(Operands[2]->getStartLoc(),
5271 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005272 // If we should not have writeback, there must not be a '!'. This is
5273 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00005274 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005275 return Error(Operands[3]->getStartLoc(),
5276 "writeback operator '!' not allowed when base register "
5277 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005278
5279 break;
5280 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005281 case ARM::t2LDMIA_UPD: {
5282 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
5283 return Error(Operands[4]->getStartLoc(),
5284 "writeback operator '!' not allowed when base register "
5285 "in register list");
5286 break;
5287 }
Jim Grosbach54026372011-11-10 23:17:11 +00005288 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
5289 // so only issue a diagnostic for thumb1. The instructions will be
5290 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005291 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005292 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005293 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
5294 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005295 return Error(Operands[2]->getStartLoc(),
5296 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005297 break;
5298 }
5299 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005300 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005301 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
5302 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005303 return Error(Operands[2]->getStartLoc(),
5304 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005305 break;
5306 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00005307 case ARM::tSTMIA_UPD: {
5308 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00005309 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00005310 return Error(Operands[4]->getStartLoc(),
5311 "registers must be in range r0-r7");
5312 break;
5313 }
Jim Grosbach189610f2011-07-26 18:25:39 +00005314 }
5315
5316 return false;
5317}
5318
Jim Grosbachd7433e22012-01-23 23:45:44 +00005319static unsigned getRealVSTOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach84defb52011-12-02 22:34:51 +00005320 switch(Opc) {
Craig Topperbc219812012-02-07 02:50:20 +00005321 default: llvm_unreachable("unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005322 // VST1LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005323 case ARM::VST1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
5324 case ARM::VST1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
5325 case ARM::VST1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
5326 case ARM::VST1LNdWB_register_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
5327 case ARM::VST1LNdWB_register_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
5328 case ARM::VST1LNdWB_register_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
5329 case ARM::VST1LNdAsm_8: Spacing = 1; return ARM::VST1LNd8;
5330 case ARM::VST1LNdAsm_16: Spacing = 1; return ARM::VST1LNd16;
5331 case ARM::VST1LNdAsm_32: Spacing = 1; return ARM::VST1LNd32;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005332
5333 // VST2LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005334 case ARM::VST2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
5335 case ARM::VST2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
5336 case ARM::VST2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
5337 case ARM::VST2LNqWB_fixed_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
5338 case ARM::VST2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005339
Jim Grosbach7945ead2012-01-24 00:43:12 +00005340 case ARM::VST2LNdWB_register_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
5341 case ARM::VST2LNdWB_register_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
5342 case ARM::VST2LNdWB_register_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
5343 case ARM::VST2LNqWB_register_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
5344 case ARM::VST2LNqWB_register_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005345
Jim Grosbach7945ead2012-01-24 00:43:12 +00005346 case ARM::VST2LNdAsm_8: Spacing = 1; return ARM::VST2LNd8;
5347 case ARM::VST2LNdAsm_16: Spacing = 1; return ARM::VST2LNd16;
5348 case ARM::VST2LNdAsm_32: Spacing = 1; return ARM::VST2LNd32;
5349 case ARM::VST2LNqAsm_16: Spacing = 2; return ARM::VST2LNq16;
5350 case ARM::VST2LNqAsm_32: Spacing = 2; return ARM::VST2LNq32;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005351
Jim Grosbach4adb1822012-01-24 00:07:41 +00005352 // VST3LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005353 case ARM::VST3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
5354 case ARM::VST3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
5355 case ARM::VST3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
5356 case ARM::VST3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNq16_UPD;
5357 case ARM::VST3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
5358 case ARM::VST3LNdWB_register_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
5359 case ARM::VST3LNdWB_register_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
5360 case ARM::VST3LNdWB_register_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
5361 case ARM::VST3LNqWB_register_Asm_16: Spacing = 2; return ARM::VST3LNq16_UPD;
5362 case ARM::VST3LNqWB_register_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
5363 case ARM::VST3LNdAsm_8: Spacing = 1; return ARM::VST3LNd8;
5364 case ARM::VST3LNdAsm_16: Spacing = 1; return ARM::VST3LNd16;
5365 case ARM::VST3LNdAsm_32: Spacing = 1; return ARM::VST3LNd32;
5366 case ARM::VST3LNqAsm_16: Spacing = 2; return ARM::VST3LNq16;
5367 case ARM::VST3LNqAsm_32: Spacing = 2; return ARM::VST3LNq32;
Jim Grosbach4adb1822012-01-24 00:07:41 +00005368
Jim Grosbachd7433e22012-01-23 23:45:44 +00005369 // VST3
Jim Grosbach7945ead2012-01-24 00:43:12 +00005370 case ARM::VST3dWB_fixed_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
5371 case ARM::VST3dWB_fixed_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
5372 case ARM::VST3dWB_fixed_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
5373 case ARM::VST3qWB_fixed_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
5374 case ARM::VST3qWB_fixed_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
5375 case ARM::VST3qWB_fixed_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
5376 case ARM::VST3dWB_register_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
5377 case ARM::VST3dWB_register_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
5378 case ARM::VST3dWB_register_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
5379 case ARM::VST3qWB_register_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
5380 case ARM::VST3qWB_register_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
5381 case ARM::VST3qWB_register_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
5382 case ARM::VST3dAsm_8: Spacing = 1; return ARM::VST3d8;
5383 case ARM::VST3dAsm_16: Spacing = 1; return ARM::VST3d16;
5384 case ARM::VST3dAsm_32: Spacing = 1; return ARM::VST3d32;
5385 case ARM::VST3qAsm_8: Spacing = 2; return ARM::VST3q8;
5386 case ARM::VST3qAsm_16: Spacing = 2; return ARM::VST3q16;
5387 case ARM::VST3qAsm_32: Spacing = 2; return ARM::VST3q32;
Jim Grosbach539aab72012-01-24 00:58:13 +00005388
Jim Grosbach88a54de2012-01-24 18:53:13 +00005389 // VST4LN
5390 case ARM::VST4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD;
5391 case ARM::VST4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD;
5392 case ARM::VST4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD;
5393 case ARM::VST4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNq16_UPD;
5394 case ARM::VST4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD;
5395 case ARM::VST4LNdWB_register_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD;
5396 case ARM::VST4LNdWB_register_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD;
5397 case ARM::VST4LNdWB_register_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD;
5398 case ARM::VST4LNqWB_register_Asm_16: Spacing = 2; return ARM::VST4LNq16_UPD;
5399 case ARM::VST4LNqWB_register_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD;
5400 case ARM::VST4LNdAsm_8: Spacing = 1; return ARM::VST4LNd8;
5401 case ARM::VST4LNdAsm_16: Spacing = 1; return ARM::VST4LNd16;
5402 case ARM::VST4LNdAsm_32: Spacing = 1; return ARM::VST4LNd32;
5403 case ARM::VST4LNqAsm_16: Spacing = 2; return ARM::VST4LNq16;
5404 case ARM::VST4LNqAsm_32: Spacing = 2; return ARM::VST4LNq32;
5405
Jim Grosbach539aab72012-01-24 00:58:13 +00005406 // VST4
5407 case ARM::VST4dWB_fixed_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
5408 case ARM::VST4dWB_fixed_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
5409 case ARM::VST4dWB_fixed_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
5410 case ARM::VST4qWB_fixed_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
5411 case ARM::VST4qWB_fixed_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
5412 case ARM::VST4qWB_fixed_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
5413 case ARM::VST4dWB_register_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
5414 case ARM::VST4dWB_register_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
5415 case ARM::VST4dWB_register_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
5416 case ARM::VST4qWB_register_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
5417 case ARM::VST4qWB_register_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
5418 case ARM::VST4qWB_register_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
5419 case ARM::VST4dAsm_8: Spacing = 1; return ARM::VST4d8;
5420 case ARM::VST4dAsm_16: Spacing = 1; return ARM::VST4d16;
5421 case ARM::VST4dAsm_32: Spacing = 1; return ARM::VST4d32;
5422 case ARM::VST4qAsm_8: Spacing = 2; return ARM::VST4q8;
5423 case ARM::VST4qAsm_16: Spacing = 2; return ARM::VST4q16;
5424 case ARM::VST4qAsm_32: Spacing = 2; return ARM::VST4q32;
Jim Grosbach84defb52011-12-02 22:34:51 +00005425 }
5426}
5427
Jim Grosbachd7433e22012-01-23 23:45:44 +00005428static unsigned getRealVLDOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005429 switch(Opc) {
Craig Topperbc219812012-02-07 02:50:20 +00005430 default: llvm_unreachable("unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005431 // VLD1LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005432 case ARM::VLD1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
5433 case ARM::VLD1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
5434 case ARM::VLD1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
5435 case ARM::VLD1LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
5436 case ARM::VLD1LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
5437 case ARM::VLD1LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
5438 case ARM::VLD1LNdAsm_8: Spacing = 1; return ARM::VLD1LNd8;
5439 case ARM::VLD1LNdAsm_16: Spacing = 1; return ARM::VLD1LNd16;
5440 case ARM::VLD1LNdAsm_32: Spacing = 1; return ARM::VLD1LNd32;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005441
5442 // VLD2LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005443 case ARM::VLD2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
5444 case ARM::VLD2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
5445 case ARM::VLD2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
5446 case ARM::VLD2LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNq16_UPD;
5447 case ARM::VLD2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
5448 case ARM::VLD2LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
5449 case ARM::VLD2LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
5450 case ARM::VLD2LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
5451 case ARM::VLD2LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD2LNq16_UPD;
5452 case ARM::VLD2LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
5453 case ARM::VLD2LNdAsm_8: Spacing = 1; return ARM::VLD2LNd8;
5454 case ARM::VLD2LNdAsm_16: Spacing = 1; return ARM::VLD2LNd16;
5455 case ARM::VLD2LNdAsm_32: Spacing = 1; return ARM::VLD2LNd32;
5456 case ARM::VLD2LNqAsm_16: Spacing = 2; return ARM::VLD2LNq16;
5457 case ARM::VLD2LNqAsm_32: Spacing = 2; return ARM::VLD2LNq32;
Jim Grosbach3a678af2012-01-23 21:53:26 +00005458
Jim Grosbach5e59f7e2012-01-24 23:47:04 +00005459 // VLD3DUP
5460 case ARM::VLD3DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD;
5461 case ARM::VLD3DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD;
5462 case ARM::VLD3DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD;
5463 case ARM::VLD3DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPq8_UPD;
5464 case ARM::VLD3DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPq16_UPD;
5465 case ARM::VLD3DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD;
5466 case ARM::VLD3DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD;
5467 case ARM::VLD3DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD;
5468 case ARM::VLD3DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD;
5469 case ARM::VLD3DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD3DUPq8_UPD;
5470 case ARM::VLD3DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD3DUPq16_UPD;
5471 case ARM::VLD3DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD;
5472 case ARM::VLD3DUPdAsm_8: Spacing = 1; return ARM::VLD3DUPd8;
5473 case ARM::VLD3DUPdAsm_16: Spacing = 1; return ARM::VLD3DUPd16;
5474 case ARM::VLD3DUPdAsm_32: Spacing = 1; return ARM::VLD3DUPd32;
5475 case ARM::VLD3DUPqAsm_8: Spacing = 2; return ARM::VLD3DUPq8;
5476 case ARM::VLD3DUPqAsm_16: Spacing = 2; return ARM::VLD3DUPq16;
5477 case ARM::VLD3DUPqAsm_32: Spacing = 2; return ARM::VLD3DUPq32;
5478
Jim Grosbach3a678af2012-01-23 21:53:26 +00005479 // VLD3LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005480 case ARM::VLD3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
5481 case ARM::VLD3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
5482 case ARM::VLD3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
5483 case ARM::VLD3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNq16_UPD;
5484 case ARM::VLD3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
5485 case ARM::VLD3LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
5486 case ARM::VLD3LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
5487 case ARM::VLD3LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
5488 case ARM::VLD3LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD3LNq16_UPD;
5489 case ARM::VLD3LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
5490 case ARM::VLD3LNdAsm_8: Spacing = 1; return ARM::VLD3LNd8;
5491 case ARM::VLD3LNdAsm_16: Spacing = 1; return ARM::VLD3LNd16;
5492 case ARM::VLD3LNdAsm_32: Spacing = 1; return ARM::VLD3LNd32;
5493 case ARM::VLD3LNqAsm_16: Spacing = 2; return ARM::VLD3LNq16;
5494 case ARM::VLD3LNqAsm_32: Spacing = 2; return ARM::VLD3LNq32;
Jim Grosbachc387fc62012-01-23 23:20:46 +00005495
5496 // VLD3
Jim Grosbach7945ead2012-01-24 00:43:12 +00005497 case ARM::VLD3dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
5498 case ARM::VLD3dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
5499 case ARM::VLD3dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
5500 case ARM::VLD3qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
5501 case ARM::VLD3qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
5502 case ARM::VLD3qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
5503 case ARM::VLD3dWB_register_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
5504 case ARM::VLD3dWB_register_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
5505 case ARM::VLD3dWB_register_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
5506 case ARM::VLD3qWB_register_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
5507 case ARM::VLD3qWB_register_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
5508 case ARM::VLD3qWB_register_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
5509 case ARM::VLD3dAsm_8: Spacing = 1; return ARM::VLD3d8;
5510 case ARM::VLD3dAsm_16: Spacing = 1; return ARM::VLD3d16;
5511 case ARM::VLD3dAsm_32: Spacing = 1; return ARM::VLD3d32;
5512 case ARM::VLD3qAsm_8: Spacing = 2; return ARM::VLD3q8;
5513 case ARM::VLD3qAsm_16: Spacing = 2; return ARM::VLD3q16;
5514 case ARM::VLD3qAsm_32: Spacing = 2; return ARM::VLD3q32;
Jim Grosbach8abe7e32012-01-24 00:43:17 +00005515
Jim Grosbache983a132012-01-24 18:37:25 +00005516 // VLD4LN
5517 case ARM::VLD4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD;
5518 case ARM::VLD4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
5519 case ARM::VLD4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
5520 case ARM::VLD4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNq16_UPD;
5521 case ARM::VLD4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
5522 case ARM::VLD4LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD;
5523 case ARM::VLD4LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
5524 case ARM::VLD4LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
5525 case ARM::VLD4LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD4LNq16_UPD;
5526 case ARM::VLD4LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
5527 case ARM::VLD4LNdAsm_8: Spacing = 1; return ARM::VLD4LNd8;
5528 case ARM::VLD4LNdAsm_16: Spacing = 1; return ARM::VLD4LNd16;
5529 case ARM::VLD4LNdAsm_32: Spacing = 1; return ARM::VLD4LNd32;
5530 case ARM::VLD4LNqAsm_16: Spacing = 2; return ARM::VLD4LNq16;
5531 case ARM::VLD4LNqAsm_32: Spacing = 2; return ARM::VLD4LNq32;
5532
Jim Grosbacha57a36a2012-01-25 00:01:08 +00005533 // VLD4DUP
5534 case ARM::VLD4DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD;
5535 case ARM::VLD4DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD;
5536 case ARM::VLD4DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD;
5537 case ARM::VLD4DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPq8_UPD;
5538 case ARM::VLD4DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPq16_UPD;
5539 case ARM::VLD4DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD;
5540 case ARM::VLD4DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD;
5541 case ARM::VLD4DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD;
5542 case ARM::VLD4DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD;
5543 case ARM::VLD4DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD4DUPq8_UPD;
5544 case ARM::VLD4DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD4DUPq16_UPD;
5545 case ARM::VLD4DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD;
5546 case ARM::VLD4DUPdAsm_8: Spacing = 1; return ARM::VLD4DUPd8;
5547 case ARM::VLD4DUPdAsm_16: Spacing = 1; return ARM::VLD4DUPd16;
5548 case ARM::VLD4DUPdAsm_32: Spacing = 1; return ARM::VLD4DUPd32;
5549 case ARM::VLD4DUPqAsm_8: Spacing = 2; return ARM::VLD4DUPq8;
5550 case ARM::VLD4DUPqAsm_16: Spacing = 2; return ARM::VLD4DUPq16;
5551 case ARM::VLD4DUPqAsm_32: Spacing = 2; return ARM::VLD4DUPq32;
5552
Jim Grosbach8abe7e32012-01-24 00:43:17 +00005553 // VLD4
5554 case ARM::VLD4dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
5555 case ARM::VLD4dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
5556 case ARM::VLD4dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
5557 case ARM::VLD4qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
5558 case ARM::VLD4qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
5559 case ARM::VLD4qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
5560 case ARM::VLD4dWB_register_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
5561 case ARM::VLD4dWB_register_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
5562 case ARM::VLD4dWB_register_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
5563 case ARM::VLD4qWB_register_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
5564 case ARM::VLD4qWB_register_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
5565 case ARM::VLD4qWB_register_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
5566 case ARM::VLD4dAsm_8: Spacing = 1; return ARM::VLD4d8;
5567 case ARM::VLD4dAsm_16: Spacing = 1; return ARM::VLD4d16;
5568 case ARM::VLD4dAsm_32: Spacing = 1; return ARM::VLD4d32;
5569 case ARM::VLD4qAsm_8: Spacing = 2; return ARM::VLD4q8;
5570 case ARM::VLD4qAsm_16: Spacing = 2; return ARM::VLD4q16;
5571 case ARM::VLD4qAsm_32: Spacing = 2; return ARM::VLD4q32;
Jim Grosbach7636bf62011-12-02 00:35:16 +00005572 }
5573}
5574
Jim Grosbach83ec8772011-11-10 23:42:14 +00005575bool ARMAsmParser::
Jim Grosbachf8fce712011-08-11 17:35:48 +00005576processInstruction(MCInst &Inst,
5577 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5578 switch (Inst.getOpcode()) {
Jim Grosbach0b4c6732012-01-18 22:46:46 +00005579 // Aliases for alternate PC+imm syntax of LDR instructions.
5580 case ARM::t2LDRpcrel:
5581 Inst.setOpcode(ARM::t2LDRpci);
5582 return true;
5583 case ARM::t2LDRBpcrel:
5584 Inst.setOpcode(ARM::t2LDRBpci);
5585 return true;
5586 case ARM::t2LDRHpcrel:
5587 Inst.setOpcode(ARM::t2LDRHpci);
5588 return true;
5589 case ARM::t2LDRSBpcrel:
5590 Inst.setOpcode(ARM::t2LDRSBpci);
5591 return true;
5592 case ARM::t2LDRSHpcrel:
5593 Inst.setOpcode(ARM::t2LDRSHpci);
5594 return true;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005595 // Handle NEON VST complex aliases.
Jim Grosbach8b31f952012-01-23 19:39:08 +00005596 case ARM::VST1LNdWB_register_Asm_8:
5597 case ARM::VST1LNdWB_register_Asm_16:
5598 case ARM::VST1LNdWB_register_Asm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005599 MCInst TmpInst;
5600 // Shuffle the operands around so the lane index operand is in the
5601 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005602 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005603 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005604 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5605 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5606 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5607 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5608 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5609 TmpInst.addOperand(Inst.getOperand(1)); // lane
5610 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5611 TmpInst.addOperand(Inst.getOperand(6));
5612 Inst = TmpInst;
5613 return true;
5614 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005615
Jim Grosbach8b31f952012-01-23 19:39:08 +00005616 case ARM::VST2LNdWB_register_Asm_8:
5617 case ARM::VST2LNdWB_register_Asm_16:
5618 case ARM::VST2LNdWB_register_Asm_32:
5619 case ARM::VST2LNqWB_register_Asm_16:
5620 case ARM::VST2LNqWB_register_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005621 MCInst TmpInst;
5622 // Shuffle the operands around so the lane index operand is in the
5623 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005624 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005625 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005626 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5627 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5628 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5629 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5630 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005631 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5632 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005633 TmpInst.addOperand(Inst.getOperand(1)); // lane
5634 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5635 TmpInst.addOperand(Inst.getOperand(6));
5636 Inst = TmpInst;
5637 return true;
5638 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005639
5640 case ARM::VST3LNdWB_register_Asm_8:
5641 case ARM::VST3LNdWB_register_Asm_16:
5642 case ARM::VST3LNdWB_register_Asm_32:
5643 case ARM::VST3LNqWB_register_Asm_16:
5644 case ARM::VST3LNqWB_register_Asm_32: {
5645 MCInst TmpInst;
5646 // Shuffle the operands around so the lane index operand is in the
5647 // right place.
5648 unsigned Spacing;
5649 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5650 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5651 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5652 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5653 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5654 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5655 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5656 Spacing));
5657 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5658 Spacing * 2));
5659 TmpInst.addOperand(Inst.getOperand(1)); // lane
5660 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5661 TmpInst.addOperand(Inst.getOperand(6));
5662 Inst = TmpInst;
5663 return true;
5664 }
5665
Jim Grosbach88a54de2012-01-24 18:53:13 +00005666 case ARM::VST4LNdWB_register_Asm_8:
5667 case ARM::VST4LNdWB_register_Asm_16:
5668 case ARM::VST4LNdWB_register_Asm_32:
5669 case ARM::VST4LNqWB_register_Asm_16:
5670 case ARM::VST4LNqWB_register_Asm_32: {
5671 MCInst TmpInst;
5672 // Shuffle the operands around so the lane index operand is in the
5673 // right place.
5674 unsigned Spacing;
5675 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5676 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5677 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5678 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5679 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5680 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5681 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5682 Spacing));
5683 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5684 Spacing * 2));
5685 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5686 Spacing * 3));
5687 TmpInst.addOperand(Inst.getOperand(1)); // lane
5688 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5689 TmpInst.addOperand(Inst.getOperand(6));
5690 Inst = TmpInst;
5691 return true;
5692 }
5693
Jim Grosbach8b31f952012-01-23 19:39:08 +00005694 case ARM::VST1LNdWB_fixed_Asm_8:
5695 case ARM::VST1LNdWB_fixed_Asm_16:
5696 case ARM::VST1LNdWB_fixed_Asm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005697 MCInst TmpInst;
5698 // Shuffle the operands around so the lane index operand is in the
5699 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005700 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005701 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005702 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5703 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5704 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5705 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5706 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5707 TmpInst.addOperand(Inst.getOperand(1)); // lane
5708 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5709 TmpInst.addOperand(Inst.getOperand(5));
5710 Inst = TmpInst;
5711 return true;
5712 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005713
Jim Grosbach8b31f952012-01-23 19:39:08 +00005714 case ARM::VST2LNdWB_fixed_Asm_8:
5715 case ARM::VST2LNdWB_fixed_Asm_16:
5716 case ARM::VST2LNdWB_fixed_Asm_32:
5717 case ARM::VST2LNqWB_fixed_Asm_16:
5718 case ARM::VST2LNqWB_fixed_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005719 MCInst TmpInst;
5720 // Shuffle the operands around so the lane index operand is in the
5721 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005722 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005723 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005724 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5725 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5726 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5727 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5728 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005729 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5730 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005731 TmpInst.addOperand(Inst.getOperand(1)); // lane
5732 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5733 TmpInst.addOperand(Inst.getOperand(5));
5734 Inst = TmpInst;
5735 return true;
5736 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005737
5738 case ARM::VST3LNdWB_fixed_Asm_8:
5739 case ARM::VST3LNdWB_fixed_Asm_16:
5740 case ARM::VST3LNdWB_fixed_Asm_32:
5741 case ARM::VST3LNqWB_fixed_Asm_16:
5742 case ARM::VST3LNqWB_fixed_Asm_32: {
5743 MCInst TmpInst;
5744 // Shuffle the operands around so the lane index operand is in the
5745 // right place.
5746 unsigned Spacing;
5747 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5748 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5749 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5750 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5751 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5752 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5753 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5754 Spacing));
5755 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5756 Spacing * 2));
5757 TmpInst.addOperand(Inst.getOperand(1)); // lane
5758 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5759 TmpInst.addOperand(Inst.getOperand(5));
5760 Inst = TmpInst;
5761 return true;
5762 }
5763
Jim Grosbach88a54de2012-01-24 18:53:13 +00005764 case ARM::VST4LNdWB_fixed_Asm_8:
5765 case ARM::VST4LNdWB_fixed_Asm_16:
5766 case ARM::VST4LNdWB_fixed_Asm_32:
5767 case ARM::VST4LNqWB_fixed_Asm_16:
5768 case ARM::VST4LNqWB_fixed_Asm_32: {
5769 MCInst TmpInst;
5770 // Shuffle the operands around so the lane index operand is in the
5771 // right place.
5772 unsigned Spacing;
5773 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5774 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5775 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5776 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5777 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5778 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5779 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5780 Spacing));
5781 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5782 Spacing * 2));
5783 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5784 Spacing * 3));
5785 TmpInst.addOperand(Inst.getOperand(1)); // lane
5786 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5787 TmpInst.addOperand(Inst.getOperand(5));
5788 Inst = TmpInst;
5789 return true;
5790 }
5791
Jim Grosbach8b31f952012-01-23 19:39:08 +00005792 case ARM::VST1LNdAsm_8:
5793 case ARM::VST1LNdAsm_16:
5794 case ARM::VST1LNdAsm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005795 MCInst TmpInst;
5796 // Shuffle the operands around so the lane index operand is in the
5797 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005798 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005799 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005800 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5801 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5802 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5803 TmpInst.addOperand(Inst.getOperand(1)); // lane
5804 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5805 TmpInst.addOperand(Inst.getOperand(5));
5806 Inst = TmpInst;
5807 return true;
5808 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005809
Jim Grosbach8b31f952012-01-23 19:39:08 +00005810 case ARM::VST2LNdAsm_8:
5811 case ARM::VST2LNdAsm_16:
5812 case ARM::VST2LNdAsm_32:
5813 case ARM::VST2LNqAsm_16:
5814 case ARM::VST2LNqAsm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005815 MCInst TmpInst;
5816 // Shuffle the operands around so the lane index operand is in the
5817 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005818 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005819 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005820 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5821 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5822 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005823 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5824 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005825 TmpInst.addOperand(Inst.getOperand(1)); // lane
5826 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5827 TmpInst.addOperand(Inst.getOperand(5));
5828 Inst = TmpInst;
5829 return true;
5830 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005831
5832 case ARM::VST3LNdAsm_8:
5833 case ARM::VST3LNdAsm_16:
5834 case ARM::VST3LNdAsm_32:
5835 case ARM::VST3LNqAsm_16:
5836 case ARM::VST3LNqAsm_32: {
5837 MCInst TmpInst;
5838 // Shuffle the operands around so the lane index operand is in the
5839 // right place.
5840 unsigned Spacing;
5841 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5842 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5843 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5844 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5845 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5846 Spacing));
5847 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5848 Spacing * 2));
5849 TmpInst.addOperand(Inst.getOperand(1)); // lane
5850 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5851 TmpInst.addOperand(Inst.getOperand(5));
5852 Inst = TmpInst;
5853 return true;
5854 }
5855
Jim Grosbach88a54de2012-01-24 18:53:13 +00005856 case ARM::VST4LNdAsm_8:
5857 case ARM::VST4LNdAsm_16:
5858 case ARM::VST4LNdAsm_32:
5859 case ARM::VST4LNqAsm_16:
5860 case ARM::VST4LNqAsm_32: {
5861 MCInst TmpInst;
5862 // Shuffle the operands around so the lane index operand is in the
5863 // right place.
5864 unsigned Spacing;
5865 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5866 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5867 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5868 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5869 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5870 Spacing));
5871 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5872 Spacing * 2));
5873 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5874 Spacing * 3));
5875 TmpInst.addOperand(Inst.getOperand(1)); // lane
5876 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5877 TmpInst.addOperand(Inst.getOperand(5));
5878 Inst = TmpInst;
5879 return true;
5880 }
5881
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005882 // Handle NEON VLD complex aliases.
Jim Grosbach8b31f952012-01-23 19:39:08 +00005883 case ARM::VLD1LNdWB_register_Asm_8:
5884 case ARM::VLD1LNdWB_register_Asm_16:
5885 case ARM::VLD1LNdWB_register_Asm_32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005886 MCInst TmpInst;
5887 // Shuffle the operands around so the lane index operand is in the
5888 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005889 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005890 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005891 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5892 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5893 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5894 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5895 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5896 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5897 TmpInst.addOperand(Inst.getOperand(1)); // lane
5898 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5899 TmpInst.addOperand(Inst.getOperand(6));
5900 Inst = TmpInst;
5901 return true;
5902 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005903
Jim Grosbach8b31f952012-01-23 19:39:08 +00005904 case ARM::VLD2LNdWB_register_Asm_8:
5905 case ARM::VLD2LNdWB_register_Asm_16:
5906 case ARM::VLD2LNdWB_register_Asm_32:
5907 case ARM::VLD2LNqWB_register_Asm_16:
5908 case ARM::VLD2LNqWB_register_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005909 MCInst TmpInst;
5910 // Shuffle the operands around so the lane index operand is in the
5911 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005912 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005913 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005914 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005915 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5916 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005917 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5918 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5919 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5920 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5921 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005922 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5923 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005924 TmpInst.addOperand(Inst.getOperand(1)); // lane
5925 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5926 TmpInst.addOperand(Inst.getOperand(6));
5927 Inst = TmpInst;
5928 return true;
5929 }
5930
Jim Grosbach3a678af2012-01-23 21:53:26 +00005931 case ARM::VLD3LNdWB_register_Asm_8:
5932 case ARM::VLD3LNdWB_register_Asm_16:
5933 case ARM::VLD3LNdWB_register_Asm_32:
5934 case ARM::VLD3LNqWB_register_Asm_16:
5935 case ARM::VLD3LNqWB_register_Asm_32: {
5936 MCInst TmpInst;
5937 // Shuffle the operands around so the lane index operand is in the
5938 // right place.
5939 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005940 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005941 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5942 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5943 Spacing));
5944 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005945 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005946 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5947 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5948 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5949 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5950 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5951 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5952 Spacing));
5953 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005954 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005955 TmpInst.addOperand(Inst.getOperand(1)); // lane
5956 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5957 TmpInst.addOperand(Inst.getOperand(6));
5958 Inst = TmpInst;
5959 return true;
5960 }
5961
Jim Grosbache983a132012-01-24 18:37:25 +00005962 case ARM::VLD4LNdWB_register_Asm_8:
5963 case ARM::VLD4LNdWB_register_Asm_16:
5964 case ARM::VLD4LNdWB_register_Asm_32:
5965 case ARM::VLD4LNqWB_register_Asm_16:
5966 case ARM::VLD4LNqWB_register_Asm_32: {
5967 MCInst TmpInst;
5968 // Shuffle the operands around so the lane index operand is in the
5969 // right place.
5970 unsigned Spacing;
5971 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
5972 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5973 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5974 Spacing));
5975 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5976 Spacing * 2));
5977 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5978 Spacing * 3));
5979 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5980 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5981 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5982 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5983 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5984 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5985 Spacing));
5986 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5987 Spacing * 2));
5988 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5989 Spacing * 3));
5990 TmpInst.addOperand(Inst.getOperand(1)); // lane
5991 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5992 TmpInst.addOperand(Inst.getOperand(6));
5993 Inst = TmpInst;
5994 return true;
5995 }
5996
Jim Grosbach8b31f952012-01-23 19:39:08 +00005997 case ARM::VLD1LNdWB_fixed_Asm_8:
5998 case ARM::VLD1LNdWB_fixed_Asm_16:
5999 case ARM::VLD1LNdWB_fixed_Asm_32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00006000 MCInst TmpInst;
6001 // Shuffle the operands around so the lane index operand is in the
6002 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006003 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006004 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00006005 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6006 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6007 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6008 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6009 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6010 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6011 TmpInst.addOperand(Inst.getOperand(1)); // lane
6012 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6013 TmpInst.addOperand(Inst.getOperand(5));
6014 Inst = TmpInst;
6015 return true;
6016 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006017
Jim Grosbach8b31f952012-01-23 19:39:08 +00006018 case ARM::VLD2LNdWB_fixed_Asm_8:
6019 case ARM::VLD2LNdWB_fixed_Asm_16:
6020 case ARM::VLD2LNdWB_fixed_Asm_32:
6021 case ARM::VLD2LNqWB_fixed_Asm_16:
6022 case ARM::VLD2LNqWB_fixed_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006023 MCInst TmpInst;
6024 // Shuffle the operands around so the lane index operand is in the
6025 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006026 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006027 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006028 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006029 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6030 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006031 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6032 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6033 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6034 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6035 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006036 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6037 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006038 TmpInst.addOperand(Inst.getOperand(1)); // lane
6039 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6040 TmpInst.addOperand(Inst.getOperand(5));
6041 Inst = TmpInst;
6042 return true;
6043 }
6044
Jim Grosbach3a678af2012-01-23 21:53:26 +00006045 case ARM::VLD3LNdWB_fixed_Asm_8:
6046 case ARM::VLD3LNdWB_fixed_Asm_16:
6047 case ARM::VLD3LNdWB_fixed_Asm_32:
6048 case ARM::VLD3LNqWB_fixed_Asm_16:
6049 case ARM::VLD3LNqWB_fixed_Asm_32: {
6050 MCInst TmpInst;
6051 // Shuffle the operands around so the lane index operand is in the
6052 // right place.
6053 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006054 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006055 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6056 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6057 Spacing));
6058 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006059 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006060 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6061 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6062 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6063 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6064 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6065 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6066 Spacing));
6067 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006068 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006069 TmpInst.addOperand(Inst.getOperand(1)); // lane
6070 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6071 TmpInst.addOperand(Inst.getOperand(5));
6072 Inst = TmpInst;
6073 return true;
6074 }
6075
Jim Grosbache983a132012-01-24 18:37:25 +00006076 case ARM::VLD4LNdWB_fixed_Asm_8:
6077 case ARM::VLD4LNdWB_fixed_Asm_16:
6078 case ARM::VLD4LNdWB_fixed_Asm_32:
6079 case ARM::VLD4LNqWB_fixed_Asm_16:
6080 case ARM::VLD4LNqWB_fixed_Asm_32: {
6081 MCInst TmpInst;
6082 // Shuffle the operands around so the lane index operand is in the
6083 // right place.
6084 unsigned Spacing;
6085 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6086 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6087 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6088 Spacing));
6089 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6090 Spacing * 2));
6091 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6092 Spacing * 3));
6093 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6094 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6095 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6096 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6097 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6098 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6099 Spacing));
6100 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6101 Spacing * 2));
6102 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6103 Spacing * 3));
6104 TmpInst.addOperand(Inst.getOperand(1)); // lane
6105 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6106 TmpInst.addOperand(Inst.getOperand(5));
6107 Inst = TmpInst;
6108 return true;
6109 }
6110
Jim Grosbach8b31f952012-01-23 19:39:08 +00006111 case ARM::VLD1LNdAsm_8:
6112 case ARM::VLD1LNdAsm_16:
6113 case ARM::VLD1LNdAsm_32: {
Jim Grosbach7636bf62011-12-02 00:35:16 +00006114 MCInst TmpInst;
6115 // Shuffle the operands around so the lane index operand is in the
6116 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006117 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006118 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach7636bf62011-12-02 00:35:16 +00006119 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6120 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6121 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6122 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6123 TmpInst.addOperand(Inst.getOperand(1)); // lane
6124 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6125 TmpInst.addOperand(Inst.getOperand(5));
6126 Inst = TmpInst;
6127 return true;
6128 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006129
Jim Grosbach8b31f952012-01-23 19:39:08 +00006130 case ARM::VLD2LNdAsm_8:
6131 case ARM::VLD2LNdAsm_16:
6132 case ARM::VLD2LNdAsm_32:
6133 case ARM::VLD2LNqAsm_16:
6134 case ARM::VLD2LNqAsm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006135 MCInst TmpInst;
6136 // Shuffle the operands around so the lane index operand is in the
6137 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006138 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006139 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006140 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006141 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6142 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006143 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6144 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6145 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006146 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6147 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006148 TmpInst.addOperand(Inst.getOperand(1)); // lane
6149 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6150 TmpInst.addOperand(Inst.getOperand(5));
6151 Inst = TmpInst;
6152 return true;
6153 }
Jim Grosbach3a678af2012-01-23 21:53:26 +00006154
6155 case ARM::VLD3LNdAsm_8:
6156 case ARM::VLD3LNdAsm_16:
6157 case ARM::VLD3LNdAsm_32:
6158 case ARM::VLD3LNqAsm_16:
6159 case ARM::VLD3LNqAsm_32: {
6160 MCInst TmpInst;
6161 // Shuffle the operands around so the lane index operand is in the
6162 // right place.
6163 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006164 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006165 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6166 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6167 Spacing));
6168 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006169 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006170 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6171 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6172 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6173 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6174 Spacing));
6175 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006176 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006177 TmpInst.addOperand(Inst.getOperand(1)); // lane
6178 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6179 TmpInst.addOperand(Inst.getOperand(5));
6180 Inst = TmpInst;
6181 return true;
6182 }
6183
Jim Grosbache983a132012-01-24 18:37:25 +00006184 case ARM::VLD4LNdAsm_8:
6185 case ARM::VLD4LNdAsm_16:
6186 case ARM::VLD4LNdAsm_32:
6187 case ARM::VLD4LNqAsm_16:
6188 case ARM::VLD4LNqAsm_32: {
6189 MCInst TmpInst;
6190 // Shuffle the operands around so the lane index operand is in the
6191 // right place.
6192 unsigned Spacing;
6193 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6194 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6195 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6196 Spacing));
6197 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6198 Spacing * 2));
6199 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6200 Spacing * 3));
6201 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6202 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6203 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6204 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6205 Spacing));
6206 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6207 Spacing * 2));
6208 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6209 Spacing * 3));
6210 TmpInst.addOperand(Inst.getOperand(1)); // lane
6211 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6212 TmpInst.addOperand(Inst.getOperand(5));
6213 Inst = TmpInst;
6214 return true;
6215 }
6216
Jim Grosbach5e59f7e2012-01-24 23:47:04 +00006217 // VLD3DUP single 3-element structure to all lanes instructions.
6218 case ARM::VLD3DUPdAsm_8:
6219 case ARM::VLD3DUPdAsm_16:
6220 case ARM::VLD3DUPdAsm_32:
6221 case ARM::VLD3DUPqAsm_8:
6222 case ARM::VLD3DUPqAsm_16:
6223 case ARM::VLD3DUPqAsm_32: {
6224 MCInst TmpInst;
6225 unsigned Spacing;
6226 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6227 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6228 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6229 Spacing));
6230 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6231 Spacing * 2));
6232 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6233 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6234 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6235 TmpInst.addOperand(Inst.getOperand(4));
6236 Inst = TmpInst;
6237 return true;
6238 }
6239
6240 case ARM::VLD3DUPdWB_fixed_Asm_8:
6241 case ARM::VLD3DUPdWB_fixed_Asm_16:
6242 case ARM::VLD3DUPdWB_fixed_Asm_32:
6243 case ARM::VLD3DUPqWB_fixed_Asm_8:
6244 case ARM::VLD3DUPqWB_fixed_Asm_16:
6245 case ARM::VLD3DUPqWB_fixed_Asm_32: {
6246 MCInst TmpInst;
6247 unsigned Spacing;
6248 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6249 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6250 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6251 Spacing));
6252 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6253 Spacing * 2));
6254 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6255 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6256 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6257 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6258 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6259 TmpInst.addOperand(Inst.getOperand(4));
6260 Inst = TmpInst;
6261 return true;
6262 }
6263
6264 case ARM::VLD3DUPdWB_register_Asm_8:
6265 case ARM::VLD3DUPdWB_register_Asm_16:
6266 case ARM::VLD3DUPdWB_register_Asm_32:
6267 case ARM::VLD3DUPqWB_register_Asm_8:
6268 case ARM::VLD3DUPqWB_register_Asm_16:
6269 case ARM::VLD3DUPqWB_register_Asm_32: {
6270 MCInst TmpInst;
6271 unsigned Spacing;
6272 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6273 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6274 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6275 Spacing));
6276 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6277 Spacing * 2));
6278 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6279 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6280 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6281 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6282 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6283 TmpInst.addOperand(Inst.getOperand(5));
6284 Inst = TmpInst;
6285 return true;
6286 }
6287
Jim Grosbachc387fc62012-01-23 23:20:46 +00006288 // VLD3 multiple 3-element structure instructions.
6289 case ARM::VLD3dAsm_8:
6290 case ARM::VLD3dAsm_16:
6291 case ARM::VLD3dAsm_32:
6292 case ARM::VLD3qAsm_8:
6293 case ARM::VLD3qAsm_16:
6294 case ARM::VLD3qAsm_32: {
6295 MCInst TmpInst;
6296 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006297 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00006298 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6299 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6300 Spacing));
6301 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6302 Spacing * 2));
6303 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6304 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6305 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6306 TmpInst.addOperand(Inst.getOperand(4));
6307 Inst = TmpInst;
6308 return true;
6309 }
6310
6311 case ARM::VLD3dWB_fixed_Asm_8:
6312 case ARM::VLD3dWB_fixed_Asm_16:
6313 case ARM::VLD3dWB_fixed_Asm_32:
6314 case ARM::VLD3qWB_fixed_Asm_8:
6315 case ARM::VLD3qWB_fixed_Asm_16:
6316 case ARM::VLD3qWB_fixed_Asm_32: {
6317 MCInst TmpInst;
6318 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006319 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00006320 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6321 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6322 Spacing));
6323 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6324 Spacing * 2));
6325 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6326 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6327 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6328 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6329 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6330 TmpInst.addOperand(Inst.getOperand(4));
6331 Inst = TmpInst;
6332 return true;
6333 }
6334
6335 case ARM::VLD3dWB_register_Asm_8:
6336 case ARM::VLD3dWB_register_Asm_16:
6337 case ARM::VLD3dWB_register_Asm_32:
6338 case ARM::VLD3qWB_register_Asm_8:
6339 case ARM::VLD3qWB_register_Asm_16:
6340 case ARM::VLD3qWB_register_Asm_32: {
6341 MCInst TmpInst;
6342 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006343 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00006344 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6345 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6346 Spacing));
6347 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6348 Spacing * 2));
6349 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6350 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6351 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6352 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6353 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6354 TmpInst.addOperand(Inst.getOperand(5));
6355 Inst = TmpInst;
6356 return true;
6357 }
6358
Jim Grosbacha57a36a2012-01-25 00:01:08 +00006359 // VLD4DUP single 3-element structure to all lanes instructions.
6360 case ARM::VLD4DUPdAsm_8:
6361 case ARM::VLD4DUPdAsm_16:
6362 case ARM::VLD4DUPdAsm_32:
6363 case ARM::VLD4DUPqAsm_8:
6364 case ARM::VLD4DUPqAsm_16:
6365 case ARM::VLD4DUPqAsm_32: {
6366 MCInst TmpInst;
6367 unsigned Spacing;
6368 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6369 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6370 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6371 Spacing));
6372 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6373 Spacing * 2));
6374 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6375 Spacing * 3));
6376 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6377 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6378 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6379 TmpInst.addOperand(Inst.getOperand(4));
6380 Inst = TmpInst;
6381 return true;
6382 }
6383
6384 case ARM::VLD4DUPdWB_fixed_Asm_8:
6385 case ARM::VLD4DUPdWB_fixed_Asm_16:
6386 case ARM::VLD4DUPdWB_fixed_Asm_32:
6387 case ARM::VLD4DUPqWB_fixed_Asm_8:
6388 case ARM::VLD4DUPqWB_fixed_Asm_16:
6389 case ARM::VLD4DUPqWB_fixed_Asm_32: {
6390 MCInst TmpInst;
6391 unsigned Spacing;
6392 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6393 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6394 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6395 Spacing));
6396 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6397 Spacing * 2));
6398 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6399 Spacing * 3));
6400 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6401 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6402 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6403 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6404 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6405 TmpInst.addOperand(Inst.getOperand(4));
6406 Inst = TmpInst;
6407 return true;
6408 }
6409
6410 case ARM::VLD4DUPdWB_register_Asm_8:
6411 case ARM::VLD4DUPdWB_register_Asm_16:
6412 case ARM::VLD4DUPdWB_register_Asm_32:
6413 case ARM::VLD4DUPqWB_register_Asm_8:
6414 case ARM::VLD4DUPqWB_register_Asm_16:
6415 case ARM::VLD4DUPqWB_register_Asm_32: {
6416 MCInst TmpInst;
6417 unsigned Spacing;
6418 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6419 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6420 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6421 Spacing));
6422 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6423 Spacing * 2));
6424 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6425 Spacing * 3));
6426 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6427 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6428 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6429 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6430 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6431 TmpInst.addOperand(Inst.getOperand(5));
6432 Inst = TmpInst;
6433 return true;
6434 }
6435
6436 // VLD4 multiple 4-element structure instructions.
Jim Grosbach8abe7e32012-01-24 00:43:17 +00006437 case ARM::VLD4dAsm_8:
6438 case ARM::VLD4dAsm_16:
6439 case ARM::VLD4dAsm_32:
6440 case ARM::VLD4qAsm_8:
6441 case ARM::VLD4qAsm_16:
6442 case ARM::VLD4qAsm_32: {
6443 MCInst TmpInst;
6444 unsigned Spacing;
6445 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6446 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6447 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6448 Spacing));
6449 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6450 Spacing * 2));
6451 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6452 Spacing * 3));
6453 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6454 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6455 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6456 TmpInst.addOperand(Inst.getOperand(4));
6457 Inst = TmpInst;
6458 return true;
6459 }
6460
6461 case ARM::VLD4dWB_fixed_Asm_8:
6462 case ARM::VLD4dWB_fixed_Asm_16:
6463 case ARM::VLD4dWB_fixed_Asm_32:
6464 case ARM::VLD4qWB_fixed_Asm_8:
6465 case ARM::VLD4qWB_fixed_Asm_16:
6466 case ARM::VLD4qWB_fixed_Asm_32: {
6467 MCInst TmpInst;
6468 unsigned Spacing;
6469 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6470 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6471 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6472 Spacing));
6473 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6474 Spacing * 2));
6475 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6476 Spacing * 3));
6477 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6478 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6479 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6480 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6481 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6482 TmpInst.addOperand(Inst.getOperand(4));
6483 Inst = TmpInst;
6484 return true;
6485 }
6486
6487 case ARM::VLD4dWB_register_Asm_8:
6488 case ARM::VLD4dWB_register_Asm_16:
6489 case ARM::VLD4dWB_register_Asm_32:
6490 case ARM::VLD4qWB_register_Asm_8:
6491 case ARM::VLD4qWB_register_Asm_16:
6492 case ARM::VLD4qWB_register_Asm_32: {
6493 MCInst TmpInst;
6494 unsigned Spacing;
6495 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6496 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6497 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6498 Spacing));
6499 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6500 Spacing * 2));
6501 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6502 Spacing * 3));
6503 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6504 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6505 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6506 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6507 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6508 TmpInst.addOperand(Inst.getOperand(5));
6509 Inst = TmpInst;
6510 return true;
6511 }
6512
Jim Grosbachd7433e22012-01-23 23:45:44 +00006513 // VST3 multiple 3-element structure instructions.
6514 case ARM::VST3dAsm_8:
6515 case ARM::VST3dAsm_16:
6516 case ARM::VST3dAsm_32:
6517 case ARM::VST3qAsm_8:
6518 case ARM::VST3qAsm_16:
6519 case ARM::VST3qAsm_32: {
6520 MCInst TmpInst;
6521 unsigned Spacing;
6522 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6523 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6524 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6525 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6526 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6527 Spacing));
6528 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6529 Spacing * 2));
6530 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6531 TmpInst.addOperand(Inst.getOperand(4));
6532 Inst = TmpInst;
6533 return true;
6534 }
6535
6536 case ARM::VST3dWB_fixed_Asm_8:
6537 case ARM::VST3dWB_fixed_Asm_16:
6538 case ARM::VST3dWB_fixed_Asm_32:
6539 case ARM::VST3qWB_fixed_Asm_8:
6540 case ARM::VST3qWB_fixed_Asm_16:
6541 case ARM::VST3qWB_fixed_Asm_32: {
6542 MCInst TmpInst;
6543 unsigned Spacing;
6544 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6545 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6546 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6547 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6548 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6549 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6550 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6551 Spacing));
6552 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6553 Spacing * 2));
6554 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6555 TmpInst.addOperand(Inst.getOperand(4));
6556 Inst = TmpInst;
6557 return true;
6558 }
6559
6560 case ARM::VST3dWB_register_Asm_8:
6561 case ARM::VST3dWB_register_Asm_16:
6562 case ARM::VST3dWB_register_Asm_32:
6563 case ARM::VST3qWB_register_Asm_8:
6564 case ARM::VST3qWB_register_Asm_16:
6565 case ARM::VST3qWB_register_Asm_32: {
6566 MCInst TmpInst;
6567 unsigned Spacing;
6568 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6569 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6570 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6571 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6572 TmpInst.addOperand(Inst.getOperand(3)); // Rm
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(4)); // CondCode
6579 TmpInst.addOperand(Inst.getOperand(5));
6580 Inst = TmpInst;
6581 return true;
6582 }
6583
Jim Grosbach539aab72012-01-24 00:58:13 +00006584 // VST4 multiple 3-element structure instructions.
6585 case ARM::VST4dAsm_8:
6586 case ARM::VST4dAsm_16:
6587 case ARM::VST4dAsm_32:
6588 case ARM::VST4qAsm_8:
6589 case ARM::VST4qAsm_16:
6590 case ARM::VST4qAsm_32: {
6591 MCInst TmpInst;
6592 unsigned Spacing;
6593 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6594 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6595 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6596 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6597 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6598 Spacing));
6599 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6600 Spacing * 2));
6601 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6602 Spacing * 3));
6603 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6604 TmpInst.addOperand(Inst.getOperand(4));
6605 Inst = TmpInst;
6606 return true;
6607 }
6608
6609 case ARM::VST4dWB_fixed_Asm_8:
6610 case ARM::VST4dWB_fixed_Asm_16:
6611 case ARM::VST4dWB_fixed_Asm_32:
6612 case ARM::VST4qWB_fixed_Asm_8:
6613 case ARM::VST4qWB_fixed_Asm_16:
6614 case ARM::VST4qWB_fixed_Asm_32: {
6615 MCInst TmpInst;
6616 unsigned Spacing;
6617 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6618 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6619 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6620 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6621 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6622 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6623 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6624 Spacing));
6625 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6626 Spacing * 2));
6627 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6628 Spacing * 3));
6629 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6630 TmpInst.addOperand(Inst.getOperand(4));
6631 Inst = TmpInst;
6632 return true;
6633 }
6634
6635 case ARM::VST4dWB_register_Asm_8:
6636 case ARM::VST4dWB_register_Asm_16:
6637 case ARM::VST4dWB_register_Asm_32:
6638 case ARM::VST4qWB_register_Asm_8:
6639 case ARM::VST4qWB_register_Asm_16:
6640 case ARM::VST4qWB_register_Asm_32: {
6641 MCInst TmpInst;
6642 unsigned Spacing;
6643 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6644 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6645 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6646 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6647 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6648 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6649 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6650 Spacing));
6651 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6652 Spacing * 2));
6653 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6654 Spacing * 3));
6655 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6656 TmpInst.addOperand(Inst.getOperand(5));
6657 Inst = TmpInst;
6658 return true;
6659 }
6660
Jim Grosbacha5378eb2012-04-11 00:15:16 +00006661 // Handle encoding choice for the shift-immediate instructions.
6662 case ARM::t2LSLri:
6663 case ARM::t2LSRri:
6664 case ARM::t2ASRri: {
6665 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6666 Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
6667 Inst.getOperand(5).getReg() == (inITBlock() ? 0 : ARM::CPSR) &&
6668 !(static_cast<ARMOperand*>(Operands[3])->isToken() &&
6669 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w")) {
6670 unsigned NewOpc;
6671 switch (Inst.getOpcode()) {
6672 default: llvm_unreachable("unexpected opcode");
6673 case ARM::t2LSLri: NewOpc = ARM::tLSLri; break;
6674 case ARM::t2LSRri: NewOpc = ARM::tLSRri; break;
6675 case ARM::t2ASRri: NewOpc = ARM::tASRri; break;
6676 }
6677 // The Thumb1 operands aren't in the same order. Awesome, eh?
6678 MCInst TmpInst;
6679 TmpInst.setOpcode(NewOpc);
6680 TmpInst.addOperand(Inst.getOperand(0));
6681 TmpInst.addOperand(Inst.getOperand(5));
6682 TmpInst.addOperand(Inst.getOperand(1));
6683 TmpInst.addOperand(Inst.getOperand(2));
6684 TmpInst.addOperand(Inst.getOperand(3));
6685 TmpInst.addOperand(Inst.getOperand(4));
6686 Inst = TmpInst;
6687 return true;
6688 }
6689 return false;
6690 }
6691
Jim Grosbach863d2af2011-12-13 22:45:11 +00006692 // Handle the Thumb2 mode MOV complex aliases.
Jim Grosbach2cc5cda2011-12-21 20:54:00 +00006693 case ARM::t2MOVsr:
6694 case ARM::t2MOVSsr: {
6695 // Which instruction to expand to depends on the CCOut operand and
6696 // whether we're in an IT block if the register operands are low
6697 // registers.
6698 bool isNarrow = false;
6699 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6700 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6701 isARMLowRegister(Inst.getOperand(2).getReg()) &&
6702 Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
6703 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsr))
6704 isNarrow = true;
6705 MCInst TmpInst;
6706 unsigned newOpc;
6707 switch(ARM_AM::getSORegShOp(Inst.getOperand(3).getImm())) {
6708 default: llvm_unreachable("unexpected opcode!");
6709 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRrr : ARM::t2ASRrr; break;
6710 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRrr : ARM::t2LSRrr; break;
6711 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLrr : ARM::t2LSLrr; break;
6712 case ARM_AM::ror: newOpc = isNarrow ? ARM::tROR : ARM::t2RORrr; break;
6713 }
6714 TmpInst.setOpcode(newOpc);
6715 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6716 if (isNarrow)
6717 TmpInst.addOperand(MCOperand::CreateReg(
6718 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6719 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6720 TmpInst.addOperand(Inst.getOperand(2)); // Rm
6721 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6722 TmpInst.addOperand(Inst.getOperand(5));
6723 if (!isNarrow)
6724 TmpInst.addOperand(MCOperand::CreateReg(
6725 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6726 Inst = TmpInst;
6727 return true;
6728 }
Jim Grosbach863d2af2011-12-13 22:45:11 +00006729 case ARM::t2MOVsi:
6730 case ARM::t2MOVSsi: {
6731 // Which instruction to expand to depends on the CCOut operand and
6732 // whether we're in an IT block if the register operands are low
6733 // registers.
6734 bool isNarrow = false;
6735 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6736 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6737 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
6738 isNarrow = true;
6739 MCInst TmpInst;
6740 unsigned newOpc;
6741 switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
6742 default: llvm_unreachable("unexpected opcode!");
6743 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
6744 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
6745 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
6746 case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
Jim Grosbach520dc782011-12-21 21:04:19 +00006747 case ARM_AM::rrx: isNarrow = false; newOpc = ARM::t2RRX; break;
Jim Grosbach863d2af2011-12-13 22:45:11 +00006748 }
6749 unsigned Ammount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
6750 if (Ammount == 32) Ammount = 0;
6751 TmpInst.setOpcode(newOpc);
6752 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6753 if (isNarrow)
6754 TmpInst.addOperand(MCOperand::CreateReg(
6755 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6756 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbach520dc782011-12-21 21:04:19 +00006757 if (newOpc != ARM::t2RRX)
6758 TmpInst.addOperand(MCOperand::CreateImm(Ammount));
Jim Grosbach863d2af2011-12-13 22:45:11 +00006759 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6760 TmpInst.addOperand(Inst.getOperand(4));
6761 if (!isNarrow)
6762 TmpInst.addOperand(MCOperand::CreateReg(
6763 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6764 Inst = TmpInst;
6765 return true;
6766 }
6767 // Handle the ARM mode MOV complex aliases.
Jim Grosbach23f22072011-11-16 18:31:45 +00006768 case ARM::ASRr:
6769 case ARM::LSRr:
6770 case ARM::LSLr:
6771 case ARM::RORr: {
6772 ARM_AM::ShiftOpc ShiftTy;
6773 switch(Inst.getOpcode()) {
6774 default: llvm_unreachable("unexpected opcode!");
6775 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
6776 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
6777 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
6778 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
6779 }
Jim Grosbach23f22072011-11-16 18:31:45 +00006780 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
6781 MCInst TmpInst;
6782 TmpInst.setOpcode(ARM::MOVsr);
6783 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6784 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6785 TmpInst.addOperand(Inst.getOperand(2)); // Rm
6786 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6787 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6788 TmpInst.addOperand(Inst.getOperand(4));
6789 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6790 Inst = TmpInst;
6791 return true;
6792 }
Jim Grosbachee10ff82011-11-10 19:18:01 +00006793 case ARM::ASRi:
6794 case ARM::LSRi:
6795 case ARM::LSLi:
6796 case ARM::RORi: {
6797 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachee10ff82011-11-10 19:18:01 +00006798 switch(Inst.getOpcode()) {
6799 default: llvm_unreachable("unexpected opcode!");
6800 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
6801 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
6802 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
6803 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
6804 }
6805 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach48b368b2011-11-16 19:05:59 +00006806 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachee10ff82011-11-10 19:18:01 +00006807 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
6808 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach71810ab2011-11-10 16:44:55 +00006809 MCInst TmpInst;
Jim Grosbachee10ff82011-11-10 19:18:01 +00006810 TmpInst.setOpcode(Opc);
Jim Grosbach71810ab2011-11-10 16:44:55 +00006811 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6812 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachee10ff82011-11-10 19:18:01 +00006813 if (Opc == ARM::MOVsi)
6814 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach71810ab2011-11-10 16:44:55 +00006815 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6816 TmpInst.addOperand(Inst.getOperand(4));
6817 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6818 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006819 return true;
Jim Grosbach71810ab2011-11-10 16:44:55 +00006820 }
Jim Grosbach48b368b2011-11-16 19:05:59 +00006821 case ARM::RRXi: {
6822 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
6823 MCInst TmpInst;
6824 TmpInst.setOpcode(ARM::MOVsi);
6825 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6826 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6827 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6828 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6829 TmpInst.addOperand(Inst.getOperand(3));
6830 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
6831 Inst = TmpInst;
6832 return true;
6833 }
Jim Grosbach0352b462011-11-10 23:58:34 +00006834 case ARM::t2LDMIA_UPD: {
6835 // If this is a load of a single register, then we should use
6836 // a post-indexed LDR instruction instead, per the ARM ARM.
6837 if (Inst.getNumOperands() != 5)
6838 return false;
6839 MCInst TmpInst;
6840 TmpInst.setOpcode(ARM::t2LDR_POST);
6841 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6842 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6843 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6844 TmpInst.addOperand(MCOperand::CreateImm(4));
6845 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6846 TmpInst.addOperand(Inst.getOperand(3));
6847 Inst = TmpInst;
6848 return true;
6849 }
6850 case ARM::t2STMDB_UPD: {
6851 // If this is a store of a single register, then we should use
6852 // a pre-indexed STR instruction instead, per the ARM ARM.
6853 if (Inst.getNumOperands() != 5)
6854 return false;
6855 MCInst TmpInst;
6856 TmpInst.setOpcode(ARM::t2STR_PRE);
6857 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6858 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6859 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6860 TmpInst.addOperand(MCOperand::CreateImm(-4));
6861 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6862 TmpInst.addOperand(Inst.getOperand(3));
6863 Inst = TmpInst;
6864 return true;
6865 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00006866 case ARM::LDMIA_UPD:
6867 // If this is a load of a single register via a 'pop', then we should use
6868 // a post-indexed LDR instruction instead, per the ARM ARM.
6869 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
6870 Inst.getNumOperands() == 5) {
6871 MCInst TmpInst;
6872 TmpInst.setOpcode(ARM::LDR_POST_IMM);
6873 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6874 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6875 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6876 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
6877 TmpInst.addOperand(MCOperand::CreateImm(4));
6878 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6879 TmpInst.addOperand(Inst.getOperand(3));
6880 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006881 return true;
Jim Grosbachf8fce712011-08-11 17:35:48 +00006882 }
6883 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00006884 case ARM::STMDB_UPD:
6885 // If this is a store of a single register via a 'push', then we should use
6886 // a pre-indexed STR instruction instead, per the ARM ARM.
6887 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
6888 Inst.getNumOperands() == 5) {
6889 MCInst TmpInst;
6890 TmpInst.setOpcode(ARM::STR_PRE_IMM);
6891 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6892 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6893 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
6894 TmpInst.addOperand(MCOperand::CreateImm(-4));
6895 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6896 TmpInst.addOperand(Inst.getOperand(3));
6897 Inst = TmpInst;
6898 }
6899 break;
Jim Grosbachda847862011-12-05 21:06:26 +00006900 case ARM::t2ADDri12:
6901 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
6902 // mnemonic was used (not "addw"), encoding T3 is preferred.
6903 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
6904 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
6905 break;
6906 Inst.setOpcode(ARM::t2ADDri);
6907 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
6908 break;
6909 case ARM::t2SUBri12:
6910 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
6911 // mnemonic was used (not "subw"), encoding T3 is preferred.
6912 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
6913 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
6914 break;
6915 Inst.setOpcode(ARM::t2SUBri);
6916 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
6917 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006918 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00006919 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6920 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6921 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6922 // to encoding T1 if <Rd> is omitted."
Jim Grosbachc0164f82012-03-30 16:31:31 +00006923 if ((unsigned)Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006924 Inst.setOpcode(ARM::tADDi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006925 return true;
6926 }
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006927 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00006928 case ARM::tSUBi8:
6929 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6930 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6931 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6932 // to encoding T1 if <Rd> is omitted."
Jim Grosbachc0164f82012-03-30 16:31:31 +00006933 if ((unsigned)Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachf67e8552011-09-16 22:58:42 +00006934 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006935 return true;
6936 }
Jim Grosbachf67e8552011-09-16 22:58:42 +00006937 break;
Jim Grosbach2d30d942012-03-30 17:20:40 +00006938 case ARM::t2ADDri:
6939 case ARM::t2SUBri: {
6940 // If the destination and first source operand are the same, and
6941 // the flags are compatible with the current IT status, use encoding T2
6942 // instead of T3. For compatibility with the system 'as'. Make sure the
6943 // wide encoding wasn't explicit.
6944 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
Jim Grosbach8f1148b2012-03-30 18:39:43 +00006945 !isARMLowRegister(Inst.getOperand(0).getReg()) ||
Jim Grosbach2d30d942012-03-30 17:20:40 +00006946 (unsigned)Inst.getOperand(2).getImm() > 255 ||
6947 ((!inITBlock() && Inst.getOperand(5).getReg() != ARM::CPSR) ||
6948 (inITBlock() && Inst.getOperand(5).getReg() != 0)) ||
6949 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6950 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
6951 break;
6952 MCInst TmpInst;
6953 TmpInst.setOpcode(Inst.getOpcode() == ARM::t2ADDri ?
6954 ARM::tADDi8 : ARM::tSUBi8);
6955 TmpInst.addOperand(Inst.getOperand(0));
6956 TmpInst.addOperand(Inst.getOperand(5));
6957 TmpInst.addOperand(Inst.getOperand(0));
6958 TmpInst.addOperand(Inst.getOperand(2));
6959 TmpInst.addOperand(Inst.getOperand(3));
6960 TmpInst.addOperand(Inst.getOperand(4));
6961 Inst = TmpInst;
6962 return true;
6963 }
Jim Grosbach927b9df2011-12-05 22:16:39 +00006964 case ARM::t2ADDrr: {
6965 // If the destination and first source operand are the same, and
6966 // there's no setting of the flags, use encoding T2 instead of T3.
6967 // Note that this is only for ADD, not SUB. This mirrors the system
6968 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
6969 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
6970 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbach713c7022011-12-05 22:27:04 +00006971 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6972 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbach927b9df2011-12-05 22:16:39 +00006973 break;
6974 MCInst TmpInst;
6975 TmpInst.setOpcode(ARM::tADDhirr);
6976 TmpInst.addOperand(Inst.getOperand(0));
6977 TmpInst.addOperand(Inst.getOperand(0));
6978 TmpInst.addOperand(Inst.getOperand(2));
6979 TmpInst.addOperand(Inst.getOperand(3));
6980 TmpInst.addOperand(Inst.getOperand(4));
6981 Inst = TmpInst;
6982 return true;
6983 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006984 case ARM::tB:
6985 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006986 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006987 Inst.setOpcode(ARM::tBcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006988 return true;
6989 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006990 break;
6991 case ARM::t2B:
6992 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006993 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006994 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006995 return true;
6996 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006997 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00006998 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00006999 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbach83ec8772011-11-10 23:42:14 +00007000 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbachc0755102011-08-31 21:17:31 +00007001 Inst.setOpcode(ARM::t2B);
Jim Grosbach83ec8772011-11-10 23:42:14 +00007002 return true;
7003 }
Jim Grosbachc0755102011-08-31 21:17:31 +00007004 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00007005 case ARM::tBcc:
7006 // If the conditional is AL, we really want tB.
Jim Grosbach83ec8772011-11-10 23:42:14 +00007007 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbach395b4532011-08-17 22:57:40 +00007008 Inst.setOpcode(ARM::tB);
Jim Grosbach83ec8772011-11-10 23:42:14 +00007009 return true;
7010 }
Jim Grosbach3ce23d32011-08-18 16:08:39 +00007011 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00007012 case ARM::tLDMIA: {
7013 // If the register list contains any high registers, or if the writeback
7014 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
7015 // instead if we're in Thumb2. Otherwise, this should have generated
7016 // an error in validateInstruction().
7017 unsigned Rn = Inst.getOperand(0).getReg();
7018 bool hasWritebackToken =
7019 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
7020 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
7021 bool listContainsBase;
7022 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
7023 (!listContainsBase && !hasWritebackToken) ||
7024 (listContainsBase && hasWritebackToken)) {
7025 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
7026 assert (isThumbTwo());
7027 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
7028 // If we're switching to the updating version, we need to insert
7029 // the writeback tied operand.
7030 if (hasWritebackToken)
7031 Inst.insert(Inst.begin(),
7032 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbach83ec8772011-11-10 23:42:14 +00007033 return true;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00007034 }
7035 break;
7036 }
Jim Grosbach8213c962011-09-16 20:50:13 +00007037 case ARM::tSTMIA_UPD: {
7038 // If the register list contains any high registers, we need to use
7039 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
7040 // should have generated an error in validateInstruction().
7041 unsigned Rn = Inst.getOperand(0).getReg();
7042 bool listContainsBase;
7043 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
7044 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
7045 assert (isThumbTwo());
7046 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbach83ec8772011-11-10 23:42:14 +00007047 return true;
Jim Grosbach8213c962011-09-16 20:50:13 +00007048 }
7049 break;
7050 }
Jim Grosbach54026372011-11-10 23:17:11 +00007051 case ARM::tPOP: {
7052 bool listContainsBase;
7053 // If the register list contains any high registers, we need to use
7054 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
7055 // should have generated an error in validateInstruction().
7056 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00007057 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00007058 assert (isThumbTwo());
7059 Inst.setOpcode(ARM::t2LDMIA_UPD);
7060 // Add the base register and writeback operands.
7061 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
7062 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00007063 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00007064 }
7065 case ARM::tPUSH: {
7066 bool listContainsBase;
7067 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00007068 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00007069 assert (isThumbTwo());
7070 Inst.setOpcode(ARM::t2STMDB_UPD);
7071 // Add the base register and writeback operands.
7072 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
7073 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00007074 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00007075 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00007076 case ARM::t2MOVi: {
7077 // If we can use the 16-bit encoding and the user didn't explicitly
7078 // request the 32-bit variant, transform it here.
7079 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
Jim Grosbachc0164f82012-03-30 16:31:31 +00007080 (unsigned)Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00007081 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
7082 Inst.getOperand(4).getReg() == ARM::CPSR) ||
7083 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00007084 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
7085 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
7086 // The operands aren't in the same order for tMOVi8...
7087 MCInst TmpInst;
7088 TmpInst.setOpcode(ARM::tMOVi8);
7089 TmpInst.addOperand(Inst.getOperand(0));
7090 TmpInst.addOperand(Inst.getOperand(4));
7091 TmpInst.addOperand(Inst.getOperand(1));
7092 TmpInst.addOperand(Inst.getOperand(2));
7093 TmpInst.addOperand(Inst.getOperand(3));
7094 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00007095 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00007096 }
7097 break;
7098 }
7099 case ARM::t2MOVr: {
7100 // If we can use the 16-bit encoding and the user didn't explicitly
7101 // request the 32-bit variant, transform it here.
7102 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
7103 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7104 Inst.getOperand(2).getImm() == ARMCC::AL &&
7105 Inst.getOperand(4).getReg() == ARM::CPSR &&
7106 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
7107 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
7108 // The operands aren't the same for tMOV[S]r... (no cc_out)
7109 MCInst TmpInst;
7110 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
7111 TmpInst.addOperand(Inst.getOperand(0));
7112 TmpInst.addOperand(Inst.getOperand(1));
7113 TmpInst.addOperand(Inst.getOperand(2));
7114 TmpInst.addOperand(Inst.getOperand(3));
7115 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00007116 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00007117 }
7118 break;
7119 }
Jim Grosbach326efe52011-09-19 20:29:33 +00007120 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00007121 case ARM::t2SXTB:
7122 case ARM::t2UXTH:
7123 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00007124 // If we can use the 16-bit encoding and the user didn't explicitly
7125 // request the 32-bit variant, transform it here.
7126 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
7127 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7128 Inst.getOperand(2).getImm() == 0 &&
7129 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
7130 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00007131 unsigned NewOpc;
7132 switch (Inst.getOpcode()) {
7133 default: llvm_unreachable("Illegal opcode!");
7134 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
7135 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
7136 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
7137 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
7138 }
Jim Grosbach326efe52011-09-19 20:29:33 +00007139 // The operands aren't the same for thumb1 (no rotate operand).
7140 MCInst TmpInst;
7141 TmpInst.setOpcode(NewOpc);
7142 TmpInst.addOperand(Inst.getOperand(0));
7143 TmpInst.addOperand(Inst.getOperand(1));
7144 TmpInst.addOperand(Inst.getOperand(3));
7145 TmpInst.addOperand(Inst.getOperand(4));
7146 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00007147 return true;
Jim Grosbach326efe52011-09-19 20:29:33 +00007148 }
7149 break;
7150 }
Jim Grosbach04b5d932011-12-20 00:59:38 +00007151 case ARM::MOVsi: {
7152 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm());
7153 if (SOpc == ARM_AM::rrx) return false;
7154 if (ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()) == 0) {
7155 // Shifting by zero is accepted as a vanilla 'MOVr'
7156 MCInst TmpInst;
7157 TmpInst.setOpcode(ARM::MOVr);
7158 TmpInst.addOperand(Inst.getOperand(0));
7159 TmpInst.addOperand(Inst.getOperand(1));
7160 TmpInst.addOperand(Inst.getOperand(3));
7161 TmpInst.addOperand(Inst.getOperand(4));
7162 TmpInst.addOperand(Inst.getOperand(5));
7163 Inst = TmpInst;
7164 return true;
7165 }
7166 return false;
7167 }
Jim Grosbach8d9550b2011-12-22 18:04:04 +00007168 case ARM::ANDrsi:
7169 case ARM::ORRrsi:
7170 case ARM::EORrsi:
7171 case ARM::BICrsi:
7172 case ARM::SUBrsi:
7173 case ARM::ADDrsi: {
7174 unsigned newOpc;
7175 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(3).getImm());
7176 if (SOpc == ARM_AM::rrx) return false;
7177 switch (Inst.getOpcode()) {
Craig Topperbc219812012-02-07 02:50:20 +00007178 default: llvm_unreachable("unexpected opcode!");
Jim Grosbach8d9550b2011-12-22 18:04:04 +00007179 case ARM::ANDrsi: newOpc = ARM::ANDrr; break;
7180 case ARM::ORRrsi: newOpc = ARM::ORRrr; break;
7181 case ARM::EORrsi: newOpc = ARM::EORrr; break;
7182 case ARM::BICrsi: newOpc = ARM::BICrr; break;
7183 case ARM::SUBrsi: newOpc = ARM::SUBrr; break;
7184 case ARM::ADDrsi: newOpc = ARM::ADDrr; break;
7185 }
7186 // If the shift is by zero, use the non-shifted instruction definition.
7187 if (ARM_AM::getSORegOffset(Inst.getOperand(3).getImm()) == 0) {
7188 MCInst TmpInst;
7189 TmpInst.setOpcode(newOpc);
7190 TmpInst.addOperand(Inst.getOperand(0));
7191 TmpInst.addOperand(Inst.getOperand(1));
7192 TmpInst.addOperand(Inst.getOperand(2));
7193 TmpInst.addOperand(Inst.getOperand(4));
7194 TmpInst.addOperand(Inst.getOperand(5));
7195 TmpInst.addOperand(Inst.getOperand(6));
7196 Inst = TmpInst;
7197 return true;
7198 }
7199 return false;
7200 }
Jim Grosbach74423e32012-01-25 19:52:01 +00007201 case ARM::ITasm:
Jim Grosbach89df9962011-08-26 21:43:41 +00007202 case ARM::t2IT: {
7203 // The mask bits for all but the first condition are represented as
7204 // the low bit of the condition code value implies 't'. We currently
7205 // always have 1 implies 't', so XOR toggle the bits if the low bit
7206 // of the condition code is zero. The encoding also expects the low
7207 // bit of the condition to be encoded as bit 4 of the mask operand,
7208 // so mask that in if needed
7209 MCOperand &MO = Inst.getOperand(1);
7210 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007211 unsigned OrigMask = Mask;
7212 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00007213 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00007214 assert(Mask && TZ <= 3 && "illegal IT mask value!");
7215 for (unsigned i = 3; i != TZ; --i)
7216 Mask ^= 1 << i;
7217 } else
7218 Mask |= 0x10;
7219 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007220
7221 // Set up the IT block state according to the IT instruction we just
7222 // matched.
7223 assert(!inITBlock() && "nested IT blocks?!");
7224 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
7225 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
7226 ITState.CurPosition = 0;
7227 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00007228 break;
7229 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00007230 }
Jim Grosbach83ec8772011-11-10 23:42:14 +00007231 return false;
Jim Grosbachf8fce712011-08-11 17:35:48 +00007232}
7233
Jim Grosbach47a0d522011-08-16 20:45:50 +00007234unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
7235 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
7236 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00007237 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00007238 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00007239 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
7240 assert(MCID.hasOptionalDef() &&
7241 "optionally flag setting instruction missing optional def operand");
7242 assert(MCID.NumOperands == Inst.getNumOperands() &&
7243 "operand count mismatch!");
7244 // Find the optional-def operand (cc_out).
7245 unsigned OpNo;
7246 for (OpNo = 0;
7247 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
7248 ++OpNo)
7249 ;
7250 // If we're parsing Thumb1, reject it completely.
7251 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
7252 return Match_MnemonicFail;
7253 // If we're parsing Thumb2, which form is legal depends on whether we're
7254 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007255 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
7256 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00007257 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007258 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
7259 inITBlock())
7260 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00007261 }
Jim Grosbach194bd892011-08-16 22:20:01 +00007262 // Some high-register supporting Thumb1 encodings only allow both registers
7263 // to be from r0-r7 when in Thumb2.
7264 else if (Opc == ARM::tADDhirr && isThumbOne() &&
7265 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7266 isARMLowRegister(Inst.getOperand(2).getReg()))
7267 return Match_RequiresThumb2;
7268 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00007269 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00007270 isARMLowRegister(Inst.getOperand(0).getReg()) &&
7271 isARMLowRegister(Inst.getOperand(1).getReg()))
7272 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00007273 return Match_Success;
7274}
7275
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007276bool ARMAsmParser::
7277MatchAndEmitInstruction(SMLoc IDLoc,
7278 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
7279 MCStreamer &Out) {
7280 MCInst Inst;
7281 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00007282 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00007283 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00007284 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00007285 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00007286 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00007287 // Context sensitive operand constraints aren't handled by the matcher,
7288 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00007289 if (validateInstruction(Inst, Operands)) {
7290 // Still progress the IT block, otherwise one wrong condition causes
7291 // nasty cascading errors.
7292 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00007293 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00007294 }
Jim Grosbach189610f2011-07-26 18:25:39 +00007295
Jim Grosbachf8fce712011-08-11 17:35:48 +00007296 // Some instructions need post-processing to, for example, tweak which
Jim Grosbach83ec8772011-11-10 23:42:14 +00007297 // encoding is selected. Loop on it while changes happen so the
7298 // individual transformations can chain off each other. E.g.,
7299 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
7300 while (processInstruction(Inst, Operands))
7301 ;
Jim Grosbachf8fce712011-08-11 17:35:48 +00007302
Jim Grosbacha1109882011-09-02 23:22:08 +00007303 // Only move forward at the very end so that everything in validate
7304 // and process gets a consistent answer about whether we're in an IT
7305 // block.
7306 forwardITPosition();
7307
Jim Grosbach74423e32012-01-25 19:52:01 +00007308 // ITasm is an ARM mode pseudo-instruction that just sets the ITblock and
7309 // doesn't actually encode.
7310 if (Inst.getOpcode() == ARM::ITasm)
7311 return false;
7312
Jim Grosbach42e6bd32012-01-26 23:20:15 +00007313 Inst.setLoc(IDLoc);
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007314 Out.EmitInstruction(Inst);
7315 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00007316 case Match_MissingFeature:
7317 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
7318 return true;
7319 case Match_InvalidOperand: {
7320 SMLoc ErrorLoc = IDLoc;
7321 if (ErrorInfo != ~0U) {
7322 if (ErrorInfo >= Operands.size())
7323 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00007324
Chris Lattnere73d4f82010-10-28 21:41:58 +00007325 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
7326 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
7327 }
Jim Grosbach16c74252010-10-29 14:46:02 +00007328
Chris Lattnere73d4f82010-10-28 21:41:58 +00007329 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007330 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00007331 case Match_MnemonicFail:
Benjamin Kramer362a05a2012-04-15 17:04:27 +00007332 return Error(IDLoc, "invalid instruction",
7333 ((ARMOperand*)Operands[0])->getLocRange());
Daniel Dunbarb4129152011-02-04 17:12:23 +00007334 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00007335 // The converter function will have already emited a diagnostic.
7336 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007337 case Match_RequiresNotITBlock:
7338 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00007339 case Match_RequiresITBlock:
7340 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00007341 case Match_RequiresV6:
7342 return Error(IDLoc, "instruction variant requires ARMv6 or later");
7343 case Match_RequiresThumb2:
7344 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00007345 }
Jim Grosbach16c74252010-10-29 14:46:02 +00007346
Eric Christopherc223e2b2010-10-29 09:26:59 +00007347 llvm_unreachable("Implement any new match types added!");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007348}
7349
Jim Grosbach1355cf12011-07-26 17:10:22 +00007350/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007351bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
7352 StringRef IDVal = DirectiveID.getIdentifier();
7353 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007354 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007355 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007356 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach9a70df92011-12-07 18:04:19 +00007357 else if (IDVal == ".arm")
7358 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007359 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007360 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007361 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007362 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007363 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007364 return parseDirectiveSyntax(DirectiveID.getLoc());
Jim Grosbacha39cda72011-12-14 02:16:11 +00007365 else if (IDVal == ".unreq")
7366 return parseDirectiveUnreq(DirectiveID.getLoc());
Jason W Kimd7c9e082011-12-20 17:38:12 +00007367 else if (IDVal == ".arch")
7368 return parseDirectiveArch(DirectiveID.getLoc());
7369 else if (IDVal == ".eabi_attribute")
7370 return parseDirectiveEabiAttr(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007371 return true;
7372}
7373
Jim Grosbach1355cf12011-07-26 17:10:22 +00007374/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007375/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00007376bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007377 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7378 for (;;) {
7379 const MCExpr *Value;
7380 if (getParser().ParseExpression(Value))
7381 return true;
7382
Chris Lattneraaec2052010-01-19 19:46:13 +00007383 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007384
7385 if (getLexer().is(AsmToken::EndOfStatement))
7386 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00007387
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007388 // FIXME: Improve diagnostic.
7389 if (getLexer().isNot(AsmToken::Comma))
7390 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007391 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007392 }
7393 }
7394
Sean Callananb9a25b72010-01-19 20:27:46 +00007395 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007396 return false;
7397}
7398
Jim Grosbach1355cf12011-07-26 17:10:22 +00007399/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00007400/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00007401bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00007402 if (getLexer().isNot(AsmToken::EndOfStatement))
7403 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007404 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007405
Jim Grosbach9a70df92011-12-07 18:04:19 +00007406 if (!isThumb())
7407 SwitchMode();
7408 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
7409 return false;
7410}
7411
7412/// parseDirectiveARM
7413/// ::= .arm
7414bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
7415 if (getLexer().isNot(AsmToken::EndOfStatement))
7416 return Error(L, "unexpected token in directive");
7417 Parser.Lex();
7418
7419 if (isThumb())
7420 SwitchMode();
7421 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby515d5092009-10-15 20:48:48 +00007422 return false;
7423}
7424
Jim Grosbach1355cf12011-07-26 17:10:22 +00007425/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00007426/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00007427bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00007428 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
7429 bool isMachO = MAI.hasSubsectionsViaSymbols();
7430 StringRef Name;
Jim Grosbachde4d8392011-12-21 22:30:16 +00007431 bool needFuncName = true;
Rafael Espindola64695402011-05-16 16:17:21 +00007432
Jim Grosbachde4d8392011-12-21 22:30:16 +00007433 // Darwin asm has (optionally) function name after .thumb_func direction
Rafael Espindola64695402011-05-16 16:17:21 +00007434 // ELF doesn't
7435 if (isMachO) {
7436 const AsmToken &Tok = Parser.getTok();
Jim Grosbachde4d8392011-12-21 22:30:16 +00007437 if (Tok.isNot(AsmToken::EndOfStatement)) {
7438 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
7439 return Error(L, "unexpected token in .thumb_func directive");
7440 Name = Tok.getIdentifier();
7441 Parser.Lex(); // Consume the identifier token.
7442 needFuncName = false;
7443 }
Rafael Espindola64695402011-05-16 16:17:21 +00007444 }
7445
Jim Grosbachde4d8392011-12-21 22:30:16 +00007446 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby515d5092009-10-15 20:48:48 +00007447 return Error(L, "unexpected token in directive");
Jim Grosbachde4d8392011-12-21 22:30:16 +00007448
7449 // Eat the end of statement and any blank lines that follow.
7450 while (getLexer().is(AsmToken::EndOfStatement))
7451 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007452
Rafael Espindola64695402011-05-16 16:17:21 +00007453 // FIXME: assuming function name will be the line following .thumb_func
Jim Grosbachde4d8392011-12-21 22:30:16 +00007454 // We really should be checking the next symbol definition even if there's
7455 // stuff in between.
7456 if (needFuncName) {
Jim Grosbachd475f862011-11-10 20:48:53 +00007457 Name = Parser.getTok().getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00007458 }
7459
Jim Grosbach642fc9c2010-11-05 22:33:53 +00007460 // Mark symbol as a thumb symbol.
7461 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
7462 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00007463 return false;
7464}
7465
Jim Grosbach1355cf12011-07-26 17:10:22 +00007466/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00007467/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00007468bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00007469 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00007470 if (Tok.isNot(AsmToken::Identifier))
7471 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00007472 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00007473 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00007474 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00007475 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00007476 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00007477 else
7478 return Error(L, "unrecognized syntax mode in .syntax directive");
7479
7480 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00007481 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007482 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007483
7484 // TODO tell the MC streamer the mode
7485 // getParser().getStreamer().Emit???();
7486 return false;
7487}
7488
Jim Grosbach1355cf12011-07-26 17:10:22 +00007489/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00007490/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00007491bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00007492 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00007493 if (Tok.isNot(AsmToken::Integer))
7494 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00007495 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00007496 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00007497 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00007498 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00007499 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007500 else
7501 return Error(L, "invalid operand to .code directive");
7502
7503 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00007504 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007505 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007506
Evan Cheng32869202011-07-08 22:36:29 +00007507 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00007508 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00007509 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00007510 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00007511 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00007512 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00007513 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00007514 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00007515 }
Jim Grosbach2a301702010-11-05 22:40:53 +00007516
Kevin Enderby515d5092009-10-15 20:48:48 +00007517 return false;
7518}
7519
Jim Grosbacha39cda72011-12-14 02:16:11 +00007520/// parseDirectiveReq
7521/// ::= name .req registername
7522bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
7523 Parser.Lex(); // Eat the '.req' token.
7524 unsigned Reg;
7525 SMLoc SRegLoc, ERegLoc;
7526 if (ParseRegister(Reg, SRegLoc, ERegLoc)) {
7527 Parser.EatToEndOfStatement();
7528 return Error(SRegLoc, "register name expected");
7529 }
7530
7531 // Shouldn't be anything else.
7532 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
7533 Parser.EatToEndOfStatement();
7534 return Error(Parser.getTok().getLoc(),
7535 "unexpected input in .req directive.");
7536 }
7537
7538 Parser.Lex(); // Consume the EndOfStatement
7539
7540 if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg)
7541 return Error(SRegLoc, "redefinition of '" + Name +
7542 "' does not match original.");
7543
7544 return false;
7545}
7546
7547/// parseDirectiveUneq
7548/// ::= .unreq registername
7549bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
7550 if (Parser.getTok().isNot(AsmToken::Identifier)) {
7551 Parser.EatToEndOfStatement();
7552 return Error(L, "unexpected input in .unreq directive.");
7553 }
7554 RegisterReqs.erase(Parser.getTok().getIdentifier());
7555 Parser.Lex(); // Eat the identifier.
7556 return false;
7557}
7558
Jason W Kimd7c9e082011-12-20 17:38:12 +00007559/// parseDirectiveArch
7560/// ::= .arch token
7561bool ARMAsmParser::parseDirectiveArch(SMLoc L) {
7562 return true;
7563}
7564
7565/// parseDirectiveEabiAttr
7566/// ::= .eabi_attribute int, int
7567bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
7568 return true;
7569}
7570
Sean Callanan90b70972010-04-07 20:29:34 +00007571extern "C" void LLVMInitializeARMAsmLexer();
7572
Kevin Enderby9c41fa82009-10-30 22:55:57 +00007573/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007574extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00007575 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
7576 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00007577 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007578}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00007579
Chris Lattner0692ee62010-09-06 19:11:01 +00007580#define GET_REGISTER_MATCHER
7581#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00007582#include "ARMGenAsmMatcher.inc"