blob: fb03a4525188252cab88d42a3699798e8bdd79d1 [file] [log] [blame]
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00001//===-- ARMAsmParser.cpp - Parse ARM assembly to MCInst instructions ------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Evan Cheng94b95502011-07-26 00:24:13 +000010#include "MCTargetDesc/ARMBaseInfo.h"
Evan Chengee04a6d2011-07-20 23:34:39 +000011#include "MCTargetDesc/ARMAddressingModes.h"
12#include "MCTargetDesc/ARMMCExpr.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000013#include "llvm/MC/MCParser/MCAsmLexer.h"
14#include "llvm/MC/MCParser/MCAsmParser.h"
15#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Rafael Espindola64695402011-05-16 16:17:21 +000016#include "llvm/MC/MCAsmInfo.h"
Jim Grosbach642fc9c2010-11-05 22:33:53 +000017#include "llvm/MC/MCContext.h"
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000018#include "llvm/MC/MCStreamer.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Evan Cheng78011362011-08-23 20:15:21 +000021#include "llvm/MC/MCInstrDesc.h"
Evan Cheng94b95502011-07-26 00:24:13 +000022#include "llvm/MC/MCRegisterInfo.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000023#include "llvm/MC/MCSubtargetInfo.h"
Evan Cheng94b95502011-07-26 00:24:13 +000024#include "llvm/MC/MCTargetAsmParser.h"
Jim Grosbach89df9962011-08-26 21:43:41 +000025#include "llvm/Support/MathExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000026#include "llvm/Support/SourceMgr.h"
Evan Cheng3e74d6f2011-08-24 18:08:43 +000027#include "llvm/Support/TargetRegistry.h"
Daniel Dunbarfa315de2010-08-11 06:37:12 +000028#include "llvm/Support/raw_ostream.h"
Jim Grosbach11e03e72011-08-22 18:50:36 +000029#include "llvm/ADT/BitVector.h"
Benjamin Kramer75ca4b92011-07-08 21:06:23 +000030#include "llvm/ADT/OwningPtr.h"
Evan Cheng94b95502011-07-26 00:24:13 +000031#include "llvm/ADT/STLExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000032#include "llvm/ADT/SmallVector.h"
Daniel Dunbar345a9a62010-08-11 06:37:20 +000033#include "llvm/ADT/StringSwitch.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000034#include "llvm/ADT/Twine.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000035
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000036using namespace llvm;
37
Chris Lattner3a697562010-10-28 17:20:03 +000038namespace {
Bill Wendling146018f2010-11-06 21:42:12 +000039
40class ARMOperand;
Jim Grosbach16c74252010-10-29 14:46:02 +000041
Jim Grosbach7636bf62011-12-02 00:35:16 +000042enum VectorLaneTy { NoLanes, AllLanes, IndexedLane };
Jim Grosbach98b05a52011-11-30 01:09:44 +000043
Evan Cheng94b95502011-07-26 00:24:13 +000044class ARMAsmParser : public MCTargetAsmParser {
Evan Chengffc0e732011-07-09 05:47:46 +000045 MCSubtargetInfo &STI;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000046 MCAsmParser &Parser;
47
Jim Grosbacha39cda72011-12-14 02:16:11 +000048 // Map of register aliases registers via the .req directive.
49 StringMap<unsigned> RegisterReqs;
50
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000051 struct {
52 ARMCC::CondCodes Cond; // Condition for IT block.
53 unsigned Mask:4; // Condition mask for instructions.
54 // Starting at first 1 (from lsb).
55 // '1' condition as indicated in IT.
56 // '0' inverse of condition (else).
57 // Count of instructions in IT block is
58 // 4 - trailingzeroes(mask)
59
60 bool FirstCond; // Explicit flag for when we're parsing the
61 // First instruction in the IT block. It's
62 // implied in the mask, so needs special
63 // handling.
64
65 unsigned CurPosition; // Current position in parsing of IT
66 // block. In range [0,3]. Initialized
67 // according to count of instructions in block.
68 // ~0U if no active IT block.
69 } ITState;
70 bool inITBlock() { return ITState.CurPosition != ~0U;}
Jim Grosbacha1109882011-09-02 23:22:08 +000071 void forwardITPosition() {
72 if (!inITBlock()) return;
73 // Move to the next instruction in the IT block, if there is one. If not,
74 // mark the block as done.
75 unsigned TZ = CountTrailingZeros_32(ITState.Mask);
76 if (++ITState.CurPosition == 5 - TZ)
77 ITState.CurPosition = ~0U; // Done with the IT block after this.
78 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000079
80
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000081 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000082 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
83
84 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000085 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
86
Jim Grosbach1355cf12011-07-26 17:10:22 +000087 int tryParseRegister();
88 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d87ec22011-07-26 20:41:24 +000089 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000090 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +000091 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000092 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
93 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbach7ce05792011-08-03 23:50:40 +000094 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
95 unsigned &ShiftAmount);
Jim Grosbach1355cf12011-07-26 17:10:22 +000096 bool parseDirectiveWord(unsigned Size, SMLoc L);
97 bool parseDirectiveThumb(SMLoc L);
Jim Grosbach9a70df92011-12-07 18:04:19 +000098 bool parseDirectiveARM(SMLoc L);
Jim Grosbach1355cf12011-07-26 17:10:22 +000099 bool parseDirectiveThumbFunc(SMLoc L);
100 bool parseDirectiveCode(SMLoc L);
101 bool parseDirectiveSyntax(SMLoc L);
Jim Grosbacha39cda72011-12-14 02:16:11 +0000102 bool parseDirectiveReq(StringRef Name, SMLoc L);
103 bool parseDirectiveUnreq(SMLoc L);
Jason W Kimd7c9e082011-12-20 17:38:12 +0000104 bool parseDirectiveArch(SMLoc L);
105 bool parseDirectiveEabiAttr(SMLoc L);
Kevin Enderby515d5092009-10-15 20:48:48 +0000106
Jim Grosbach1355cf12011-07-26 17:10:22 +0000107 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach89df9962011-08-26 21:43:41 +0000108 bool &CarrySetting, unsigned &ProcessorIMod,
109 StringRef &ITMask);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000110 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +0000111 bool &CanAcceptPredicationCode);
Jim Grosbach16c74252010-10-29 14:46:02 +0000112
Evan Chengebdeeab2011-07-08 01:53:10 +0000113 bool isThumb() const {
114 // FIXME: Can tablegen auto-generate this?
Evan Chengffc0e732011-07-09 05:47:46 +0000115 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000116 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000117 bool isThumbOne() const {
Evan Chengffc0e732011-07-09 05:47:46 +0000118 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000119 }
Jim Grosbach47a0d522011-08-16 20:45:50 +0000120 bool isThumbTwo() const {
121 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
122 }
Jim Grosbach194bd892011-08-16 22:20:01 +0000123 bool hasV6Ops() const {
124 return STI.getFeatureBits() & ARM::HasV6Ops;
125 }
James Molloyacad68d2011-09-28 14:21:38 +0000126 bool hasV7Ops() const {
127 return STI.getFeatureBits() & ARM::HasV7Ops;
128 }
Evan Cheng32869202011-07-08 22:36:29 +0000129 void SwitchMode() {
Evan Chengffc0e732011-07-09 05:47:46 +0000130 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
131 setAvailableFeatures(FB);
Evan Cheng32869202011-07-08 22:36:29 +0000132 }
James Molloyacad68d2011-09-28 14:21:38 +0000133 bool isMClass() const {
134 return STI.getFeatureBits() & ARM::FeatureMClass;
135 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000136
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000137 /// @name Auto-generated Match Functions
138 /// {
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000139
Chris Lattner0692ee62010-09-06 19:11:01 +0000140#define GET_ASSEMBLER_HEADER
141#include "ARMGenAsmMatcher.inc"
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000142
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000143 /// }
144
Jim Grosbach89df9962011-08-26 21:43:41 +0000145 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000146 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000147 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000148 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000149 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000150 OperandMatchResultTy parseCoprocOptionOperand(
151 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000152 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000153 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000154 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000155 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000156 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000157 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachf6c05252011-07-21 17:23:04 +0000158 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
159 StringRef Op, int Low, int High);
160 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
161 return parsePKHImm(O, "lsl", 0, 31);
162 }
163 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
164 return parsePKHImm(O, "asr", 1, 32);
165 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000166 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach580f4a92011-07-25 22:20:28 +0000167 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000168 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000169 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000170 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach251bf252011-08-10 21:56:18 +0000171 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9d390362011-10-03 23:38:36 +0000172 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach862019c2011-10-18 23:02:30 +0000173 OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7636bf62011-12-02 00:35:16 +0000174 OperandMatchResultTy parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000175
176 // Asm Match Converter Methods
Jim Grosbacha77295d2011-09-08 22:07:06 +0000177 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
178 const SmallVectorImpl<MCParsedAsmOperand*> &);
179 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
180 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheeec0252011-09-08 00:39:19 +0000181 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
182 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachee2c2a42011-09-16 21:55:56 +0000183 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
184 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000185 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000186 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson9ab0f252011-08-26 20:43:14 +0000187 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
188 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach548340c2011-08-11 19:22:40 +0000189 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
190 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000191 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000192 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7b8f46c2011-08-11 21:17:22 +0000193 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
194 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000195 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
196 const SmallVectorImpl<MCParsedAsmOperand*> &);
197 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
198 const SmallVectorImpl<MCParsedAsmOperand*> &);
199 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
200 const SmallVectorImpl<MCParsedAsmOperand*> &);
201 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
202 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000203 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
204 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach14605d12011-08-11 20:28:23 +0000205 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
206 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach623a4542011-08-10 22:42:16 +0000207 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
208 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach88ae2bc2011-08-19 22:07:46 +0000209 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
210 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach12431322011-10-24 22:16:58 +0000211 bool cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
212 const SmallVectorImpl<MCParsedAsmOperand*> &);
213 bool cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
214 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach4334e032011-10-31 21:50:31 +0000215 bool cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
216 const SmallVectorImpl<MCParsedAsmOperand*> &);
217 bool cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
218 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach189610f2011-07-26 18:25:39 +0000219
220 bool validateInstruction(MCInst &Inst,
221 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach83ec8772011-11-10 23:42:14 +0000222 bool processInstruction(MCInst &Inst,
Jim Grosbachf8fce712011-08-11 17:35:48 +0000223 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachd54b4e62011-08-16 21:12:37 +0000224 bool shouldOmitCCOutOperand(StringRef Mnemonic,
225 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach189610f2011-07-26 18:25:39 +0000226
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000227public:
Jim Grosbach47a0d522011-08-16 20:45:50 +0000228 enum ARMMatchResultTy {
Jim Grosbach194bd892011-08-16 22:20:01 +0000229 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000230 Match_RequiresNotITBlock,
Jim Grosbach194bd892011-08-16 22:20:01 +0000231 Match_RequiresV6,
232 Match_RequiresThumb2
Jim Grosbach47a0d522011-08-16 20:45:50 +0000233 };
234
Evan Chengffc0e732011-07-09 05:47:46 +0000235 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng94b95502011-07-26 00:24:13 +0000236 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Chengebdeeab2011-07-08 01:53:10 +0000237 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng32869202011-07-08 22:36:29 +0000238
Evan Chengebdeeab2011-07-08 01:53:10 +0000239 // Initialize the set of available features.
Evan Chengffc0e732011-07-09 05:47:46 +0000240 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000241
242 // Not in an ITBlock to start with.
243 ITState.CurPosition = ~0U;
Evan Chengebdeeab2011-07-08 01:53:10 +0000244 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000245
Jim Grosbach1355cf12011-07-26 17:10:22 +0000246 // Implementation of the MCTargetAsmParser interface:
247 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
248 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbach189610f2011-07-26 18:25:39 +0000249 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000250 bool ParseDirective(AsmToken DirectiveID);
251
Jim Grosbach47a0d522011-08-16 20:45:50 +0000252 unsigned checkTargetMatchPredicate(MCInst &Inst);
253
Jim Grosbach1355cf12011-07-26 17:10:22 +0000254 bool MatchAndEmitInstruction(SMLoc IDLoc,
255 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
256 MCStreamer &Out);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000257};
Jim Grosbach16c74252010-10-29 14:46:02 +0000258} // end anonymous namespace
259
Chris Lattner3a697562010-10-28 17:20:03 +0000260namespace {
261
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000262/// ARMOperand - Instances of this class represent a parsed ARM machine
263/// instruction.
Bill Wendling146018f2010-11-06 21:42:12 +0000264class ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000265 enum KindTy {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000266 k_CondCode,
267 k_CCOut,
268 k_ITCondMask,
269 k_CoprocNum,
270 k_CoprocReg,
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000271 k_CoprocOption,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000272 k_Immediate,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000273 k_MemBarrierOpt,
274 k_Memory,
275 k_PostIndexRegister,
276 k_MSRMask,
277 k_ProcIFlags,
Jim Grosbach460a9052011-10-07 23:56:00 +0000278 k_VectorIndex,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000279 k_Register,
280 k_RegisterList,
281 k_DPRRegisterList,
282 k_SPRRegisterList,
Jim Grosbach862019c2011-10-18 23:02:30 +0000283 k_VectorList,
Jim Grosbach98b05a52011-11-30 01:09:44 +0000284 k_VectorListAllLanes,
Jim Grosbach7636bf62011-12-02 00:35:16 +0000285 k_VectorListIndexed,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000286 k_ShiftedRegister,
287 k_ShiftedImmediate,
288 k_ShifterImmediate,
289 k_RotateImmediate,
290 k_BitfieldDescriptor,
291 k_Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000292 } Kind;
293
Sean Callanan76264762010-04-02 22:27:05 +0000294 SMLoc StartLoc, EndLoc;
Bill Wendling24d22d22010-11-18 21:50:54 +0000295 SmallVector<unsigned, 8> Registers;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000296
297 union {
298 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000299 ARMCC::CondCodes Val;
300 } CC;
301
302 struct {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000303 unsigned Val;
304 } Cop;
305
306 struct {
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000307 unsigned Val;
308 } CoprocOption;
309
310 struct {
Jim Grosbach89df9962011-08-26 21:43:41 +0000311 unsigned Mask:4;
312 } ITMask;
313
314 struct {
315 ARM_MB::MemBOpt Val;
316 } MBOpt;
317
318 struct {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000319 ARM_PROC::IFlags Val;
320 } IFlags;
321
322 struct {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000323 unsigned Val;
324 } MMask;
325
326 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000327 const char *Data;
328 unsigned Length;
329 } Tok;
330
331 struct {
332 unsigned RegNum;
333 } Reg;
334
Jim Grosbach862019c2011-10-18 23:02:30 +0000335 // A vector register list is a sequential list of 1 to 4 registers.
336 struct {
337 unsigned RegNum;
338 unsigned Count;
Jim Grosbach7636bf62011-12-02 00:35:16 +0000339 unsigned LaneIndex;
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +0000340 bool isDoubleSpaced;
Jim Grosbach862019c2011-10-18 23:02:30 +0000341 } VectorList;
342
Bill Wendling8155e5b2010-11-06 22:19:43 +0000343 struct {
Jim Grosbach460a9052011-10-07 23:56:00 +0000344 unsigned Val;
345 } VectorIndex;
346
347 struct {
Kevin Enderbycfe07242009-10-13 22:19:02 +0000348 const MCExpr *Val;
349 } Imm;
Jim Grosbach16c74252010-10-29 14:46:02 +0000350
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +0000351 /// Combined record for all forms of ARM address expressions.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000352 struct {
353 unsigned BaseRegNum;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000354 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
355 // was specified.
356 const MCConstantExpr *OffsetImm; // Offset immediate value
357 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
358 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbach57dcb852011-10-11 17:29:55 +0000359 unsigned ShiftImm; // shift for OffsetReg.
360 unsigned Alignment; // 0 = no alignment specified
Jim Grosbacheeaf1c12011-12-19 18:31:43 +0000361 // n = alignment in bytes (2, 4, 8, 16, or 32)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000362 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbache53c87b2011-10-11 15:59:20 +0000363 } Memory;
Owen Anderson00828302011-03-18 22:50:18 +0000364
365 struct {
Jim Grosbach7ce05792011-08-03 23:50:40 +0000366 unsigned RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000367 bool isAdd;
368 ARM_AM::ShiftOpc ShiftTy;
369 unsigned ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000370 } PostIdxReg;
371
372 struct {
Jim Grosbach580f4a92011-07-25 22:20:28 +0000373 bool isASR;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000374 unsigned Imm;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000375 } ShifterImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000376 struct {
377 ARM_AM::ShiftOpc ShiftTy;
378 unsigned SrcReg;
379 unsigned ShiftReg;
380 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000381 } RegShiftedReg;
Owen Anderson92a20222011-07-21 18:54:16 +0000382 struct {
383 ARM_AM::ShiftOpc ShiftTy;
384 unsigned SrcReg;
385 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000386 } RegShiftedImm;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000387 struct {
388 unsigned Imm;
389 } RotImm;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000390 struct {
391 unsigned LSB;
392 unsigned Width;
393 } Bitfield;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000394 };
Jim Grosbach16c74252010-10-29 14:46:02 +0000395
Bill Wendling146018f2010-11-06 21:42:12 +0000396 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
397public:
Sean Callanan76264762010-04-02 22:27:05 +0000398 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
399 Kind = o.Kind;
400 StartLoc = o.StartLoc;
401 EndLoc = o.EndLoc;
402 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000403 case k_CondCode:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000404 CC = o.CC;
405 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000406 case k_ITCondMask:
Jim Grosbach89df9962011-08-26 21:43:41 +0000407 ITMask = o.ITMask;
408 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000409 case k_Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000410 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000411 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000412 case k_CCOut:
413 case k_Register:
Sean Callanan76264762010-04-02 22:27:05 +0000414 Reg = o.Reg;
415 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000416 case k_RegisterList:
417 case k_DPRRegisterList:
418 case k_SPRRegisterList:
Bill Wendling24d22d22010-11-18 21:50:54 +0000419 Registers = o.Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000420 break;
Jim Grosbach862019c2011-10-18 23:02:30 +0000421 case k_VectorList:
Jim Grosbach98b05a52011-11-30 01:09:44 +0000422 case k_VectorListAllLanes:
Jim Grosbach7636bf62011-12-02 00:35:16 +0000423 case k_VectorListIndexed:
Jim Grosbach862019c2011-10-18 23:02:30 +0000424 VectorList = o.VectorList;
425 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000426 case k_CoprocNum:
427 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000428 Cop = o.Cop;
429 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000430 case k_CoprocOption:
431 CoprocOption = o.CoprocOption;
432 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000433 case k_Immediate:
Sean Callanan76264762010-04-02 22:27:05 +0000434 Imm = o.Imm;
435 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000436 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000437 MBOpt = o.MBOpt;
438 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000439 case k_Memory:
Jim Grosbache53c87b2011-10-11 15:59:20 +0000440 Memory = o.Memory;
Sean Callanan76264762010-04-02 22:27:05 +0000441 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000442 case k_PostIndexRegister:
Jim Grosbach7ce05792011-08-03 23:50:40 +0000443 PostIdxReg = o.PostIdxReg;
444 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000445 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000446 MMask = o.MMask;
447 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000448 case k_ProcIFlags:
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000449 IFlags = o.IFlags;
Owen Anderson00828302011-03-18 22:50:18 +0000450 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000451 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +0000452 ShifterImm = o.ShifterImm;
Owen Anderson00828302011-03-18 22:50:18 +0000453 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000454 case k_ShiftedRegister:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000455 RegShiftedReg = o.RegShiftedReg;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000456 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000457 case k_ShiftedImmediate:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000458 RegShiftedImm = o.RegShiftedImm;
Owen Anderson92a20222011-07-21 18:54:16 +0000459 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000460 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000461 RotImm = o.RotImm;
462 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000463 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000464 Bitfield = o.Bitfield;
465 break;
Jim Grosbach460a9052011-10-07 23:56:00 +0000466 case k_VectorIndex:
467 VectorIndex = o.VectorIndex;
468 break;
Sean Callanan76264762010-04-02 22:27:05 +0000469 }
470 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000471
Sean Callanan76264762010-04-02 22:27:05 +0000472 /// getStartLoc - Get the location of the first token of this operand.
473 SMLoc getStartLoc() const { return StartLoc; }
474 /// getEndLoc - Get the location of the last token of this operand.
475 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000476
Daniel Dunbar8462b302010-08-11 06:36:53 +0000477 ARMCC::CondCodes getCondCode() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000478 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000479 return CC.Val;
480 }
481
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000482 unsigned getCoproc() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000483 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000484 return Cop.Val;
485 }
486
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000487 StringRef getToken() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000488 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000489 return StringRef(Tok.Data, Tok.Length);
490 }
491
492 unsigned getReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000493 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling7729e062010-11-09 22:44:22 +0000494 return Reg.RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000495 }
496
Bill Wendling5fa22a12010-11-09 23:28:44 +0000497 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000498 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
499 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling24d22d22010-11-18 21:50:54 +0000500 return Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000501 }
502
Kevin Enderbycfe07242009-10-13 22:19:02 +0000503 const MCExpr *getImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000504 assert(isImm() && "Invalid access!");
Kevin Enderbycfe07242009-10-13 22:19:02 +0000505 return Imm.Val;
506 }
507
Jim Grosbach460a9052011-10-07 23:56:00 +0000508 unsigned getVectorIndex() const {
509 assert(Kind == k_VectorIndex && "Invalid access!");
510 return VectorIndex.Val;
511 }
512
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000513 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000514 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000515 return MBOpt.Val;
516 }
517
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000518 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000519 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000520 return IFlags.Val;
521 }
522
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000523 unsigned getMSRMask() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000524 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000525 return MMask.Val;
526 }
527
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000528 bool isCoprocNum() const { return Kind == k_CoprocNum; }
529 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000530 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000531 bool isCondCode() const { return Kind == k_CondCode; }
532 bool isCCOut() const { return Kind == k_CCOut; }
533 bool isITMask() const { return Kind == k_ITCondMask; }
534 bool isITCondCode() const { return Kind == k_CondCode; }
535 bool isImm() const { return Kind == k_Immediate; }
Jim Grosbach51222d12012-01-20 18:09:51 +0000536 bool isFPImm() const {
537 if (!isImm()) return false;
538 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
539 if (!CE) return false;
540 int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
541 return Val != -1;
542 }
Jim Grosbach4050bc42011-12-22 22:19:05 +0000543 bool isFBits16() const {
544 if (!isImm()) return false;
545 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
546 if (!CE) return false;
547 int64_t Value = CE->getValue();
548 return Value >= 0 && Value <= 16;
549 }
550 bool isFBits32() const {
551 if (!isImm()) return false;
552 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
553 if (!CE) return false;
554 int64_t Value = CE->getValue();
555 return Value >= 1 && Value <= 32;
556 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000557 bool isImm8s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000558 if (!isImm()) return false;
Jim Grosbacha77295d2011-09-08 22:07:06 +0000559 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
560 if (!CE) return false;
561 int64_t Value = CE->getValue();
562 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
563 }
Jim Grosbach72f39f82011-08-24 21:22:15 +0000564 bool isImm0_1020s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000565 if (!isImm()) return false;
Jim Grosbach72f39f82011-08-24 21:22:15 +0000566 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
567 if (!CE) return false;
568 int64_t Value = CE->getValue();
569 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
570 }
571 bool isImm0_508s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000572 if (!isImm()) return false;
Jim Grosbach72f39f82011-08-24 21:22:15 +0000573 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
574 if (!CE) return false;
575 int64_t Value = CE->getValue();
576 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
577 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000578 bool isImm0_255() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000579 if (!isImm()) return false;
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000580 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
581 if (!CE) return false;
582 int64_t Value = CE->getValue();
583 return Value >= 0 && Value < 256;
584 }
Jim Grosbach587f5062011-12-02 23:34:39 +0000585 bool isImm0_1() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000586 if (!isImm()) return false;
Jim Grosbach587f5062011-12-02 23:34:39 +0000587 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
588 if (!CE) return false;
589 int64_t Value = CE->getValue();
590 return Value >= 0 && Value < 2;
591 }
592 bool isImm0_3() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000593 if (!isImm()) return false;
Jim Grosbach587f5062011-12-02 23:34:39 +0000594 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
595 if (!CE) return false;
596 int64_t Value = CE->getValue();
597 return Value >= 0 && Value < 4;
598 }
Jim Grosbach83ab0702011-07-13 22:01:08 +0000599 bool isImm0_7() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000600 if (!isImm()) return false;
Jim Grosbach83ab0702011-07-13 22:01:08 +0000601 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
602 if (!CE) return false;
603 int64_t Value = CE->getValue();
604 return Value >= 0 && Value < 8;
605 }
606 bool isImm0_15() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000607 if (!isImm()) return false;
Jim Grosbach83ab0702011-07-13 22:01:08 +0000608 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
609 if (!CE) return false;
610 int64_t Value = CE->getValue();
611 return Value >= 0 && Value < 16;
612 }
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000613 bool isImm0_31() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000614 if (!isImm()) return false;
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000615 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
616 if (!CE) return false;
617 int64_t Value = CE->getValue();
618 return Value >= 0 && Value < 32;
619 }
Jim Grosbach730fe6c2011-12-08 01:30:04 +0000620 bool isImm0_63() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000621 if (!isImm()) return false;
Jim Grosbach730fe6c2011-12-08 01:30:04 +0000622 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
623 if (!CE) return false;
624 int64_t Value = CE->getValue();
625 return Value >= 0 && Value < 64;
626 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000627 bool isImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000628 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000629 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
630 if (!CE) return false;
631 int64_t Value = CE->getValue();
632 return Value == 8;
633 }
634 bool isImm16() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000635 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000636 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
637 if (!CE) return false;
638 int64_t Value = CE->getValue();
639 return Value == 16;
640 }
641 bool isImm32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000642 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000643 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
644 if (!CE) return false;
645 int64_t Value = CE->getValue();
646 return Value == 32;
647 }
Jim Grosbach6b044c22011-12-08 22:06:06 +0000648 bool isShrImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000649 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000650 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
651 if (!CE) return false;
652 int64_t Value = CE->getValue();
653 return Value > 0 && Value <= 8;
654 }
655 bool isShrImm16() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000656 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000657 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
658 if (!CE) return false;
659 int64_t Value = CE->getValue();
660 return Value > 0 && Value <= 16;
661 }
662 bool isShrImm32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000663 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000664 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
665 if (!CE) return false;
666 int64_t Value = CE->getValue();
667 return Value > 0 && Value <= 32;
668 }
669 bool isShrImm64() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000670 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000671 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
672 if (!CE) return false;
673 int64_t Value = CE->getValue();
674 return Value > 0 && Value <= 64;
675 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000676 bool isImm1_7() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000677 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000678 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
679 if (!CE) return false;
680 int64_t Value = CE->getValue();
681 return Value > 0 && Value < 8;
682 }
683 bool isImm1_15() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000684 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000685 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
686 if (!CE) return false;
687 int64_t Value = CE->getValue();
688 return Value > 0 && Value < 16;
689 }
690 bool isImm1_31() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000691 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000692 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
693 if (!CE) return false;
694 int64_t Value = CE->getValue();
695 return Value > 0 && Value < 32;
696 }
Jim Grosbachf4943352011-07-25 23:09:14 +0000697 bool isImm1_16() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000698 if (!isImm()) return false;
Jim Grosbachf4943352011-07-25 23:09:14 +0000699 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
700 if (!CE) return false;
701 int64_t Value = CE->getValue();
702 return Value > 0 && Value < 17;
703 }
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000704 bool isImm1_32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000705 if (!isImm()) return false;
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000706 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
707 if (!CE) return false;
708 int64_t Value = CE->getValue();
709 return Value > 0 && Value < 33;
710 }
Jim Grosbachee10ff82011-11-10 19:18:01 +0000711 bool isImm0_32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000712 if (!isImm()) return false;
Jim Grosbachee10ff82011-11-10 19:18:01 +0000713 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
714 if (!CE) return false;
715 int64_t Value = CE->getValue();
716 return Value >= 0 && Value < 33;
717 }
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000718 bool isImm0_65535() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000719 if (!isImm()) return false;
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000720 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
721 if (!CE) return false;
722 int64_t Value = CE->getValue();
723 return Value >= 0 && Value < 65536;
724 }
Jim Grosbachffa32252011-07-19 19:13:28 +0000725 bool isImm0_65535Expr() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000726 if (!isImm()) return false;
Jim Grosbachffa32252011-07-19 19:13:28 +0000727 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
728 // If it's not a constant expression, it'll generate a fixup and be
729 // handled later.
730 if (!CE) return true;
731 int64_t Value = CE->getValue();
732 return Value >= 0 && Value < 65536;
733 }
Jim Grosbached838482011-07-26 16:24:27 +0000734 bool isImm24bit() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000735 if (!isImm()) return false;
Jim Grosbached838482011-07-26 16:24:27 +0000736 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
737 if (!CE) return false;
738 int64_t Value = CE->getValue();
739 return Value >= 0 && Value <= 0xffffff;
740 }
Jim Grosbach70939ee2011-08-17 21:51:27 +0000741 bool isImmThumbSR() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000742 if (!isImm()) return false;
Jim Grosbach70939ee2011-08-17 21:51:27 +0000743 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
744 if (!CE) return false;
745 int64_t Value = CE->getValue();
746 return Value > 0 && Value < 33;
747 }
Jim Grosbachf6c05252011-07-21 17:23:04 +0000748 bool isPKHLSLImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000749 if (!isImm()) return false;
Jim Grosbachf6c05252011-07-21 17:23:04 +0000750 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
751 if (!CE) return false;
752 int64_t Value = CE->getValue();
753 return Value >= 0 && Value < 32;
754 }
755 bool isPKHASRImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000756 if (!isImm()) return false;
Jim Grosbachf6c05252011-07-21 17:23:04 +0000757 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
758 if (!CE) return false;
759 int64_t Value = CE->getValue();
760 return Value > 0 && Value <= 32;
761 }
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000762 bool isARMSOImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000763 if (!isImm()) return false;
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000764 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
765 if (!CE) return false;
766 int64_t Value = CE->getValue();
767 return ARM_AM::getSOImmVal(Value) != -1;
768 }
Jim Grosbache70ec842011-10-28 22:50:54 +0000769 bool isARMSOImmNot() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000770 if (!isImm()) return false;
Jim Grosbache70ec842011-10-28 22:50:54 +0000771 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
772 if (!CE) return false;
773 int64_t Value = CE->getValue();
774 return ARM_AM::getSOImmVal(~Value) != -1;
775 }
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000776 bool isARMSOImmNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000777 if (!isImm()) return false;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000778 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
779 if (!CE) return false;
780 int64_t Value = CE->getValue();
781 return ARM_AM::getSOImmVal(-Value) != -1;
782 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000783 bool isT2SOImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000784 if (!isImm()) return false;
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000785 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
786 if (!CE) return false;
787 int64_t Value = CE->getValue();
788 return ARM_AM::getT2SOImmVal(Value) != -1;
789 }
Jim Grosbach89a63372011-10-28 22:36:30 +0000790 bool isT2SOImmNot() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000791 if (!isImm()) return false;
Jim Grosbach89a63372011-10-28 22:36:30 +0000792 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
793 if (!CE) return false;
794 int64_t Value = CE->getValue();
795 return ARM_AM::getT2SOImmVal(~Value) != -1;
796 }
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000797 bool isT2SOImmNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000798 if (!isImm()) return false;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000799 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
800 if (!CE) return false;
801 int64_t Value = CE->getValue();
802 return ARM_AM::getT2SOImmVal(-Value) != -1;
803 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000804 bool isSetEndImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000805 if (!isImm()) return false;
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000806 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
807 if (!CE) return false;
808 int64_t Value = CE->getValue();
809 return Value == 1 || Value == 0;
810 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000811 bool isReg() const { return Kind == k_Register; }
812 bool isRegList() const { return Kind == k_RegisterList; }
813 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
814 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
815 bool isToken() const { return Kind == k_Token; }
816 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
817 bool isMemory() const { return Kind == k_Memory; }
818 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
819 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
820 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
821 bool isRotImm() const { return Kind == k_RotateImmediate; }
822 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
823 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000824 bool isPostIdxReg() const {
Jim Grosbach430052b2011-11-14 17:52:47 +0000825 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000826 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000827 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000828 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000829 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000830 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000831 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
832 (alignOK || Memory.Alignment == 0);
833 }
Jim Grosbach0b4c6732012-01-18 22:46:46 +0000834 bool isMemPCRelImm12() const {
835 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
836 return false;
837 // Base register must be PC.
838 if (Memory.BaseRegNum != ARM::PC)
839 return false;
840 // Immediate offset in range [-4095, 4095].
841 if (!Memory.OffsetImm) return true;
842 int64_t Val = Memory.OffsetImm->getValue();
843 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
844 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000845 bool isAlignedMemory() const {
846 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000847 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000848 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000849 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000850 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000851 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000852 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000853 if (!Memory.OffsetImm) return true;
854 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000855 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000856 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000857 bool isAM2OffsetImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000858 if (!isImm()) return false;
Jim Grosbach039c2e12011-08-04 23:01:30 +0000859 // Immediate offset in range [-4095, 4095].
860 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
861 if (!CE) return false;
862 int64_t Val = CE->getValue();
863 return Val > -4096 && Val < 4096;
864 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000865 bool isAddrMode3() const {
Jim Grosbach2f196742011-12-19 23:06:24 +0000866 // If we have an immediate that's not a constant, treat it as a label
867 // reference needing a fixup. If it is a constant, it's something else
868 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000869 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach2f196742011-12-19 23:06:24 +0000870 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000871 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000872 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000873 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000874 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000875 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000876 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000877 if (!Memory.OffsetImm) return true;
878 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000879 return Val > -256 && Val < 256;
880 }
881 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000882 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000883 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000884 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000885 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
886 // Immediate offset in range [-255, 255].
887 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
888 if (!CE) return false;
889 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000890 // Special case, #-0 is INT32_MIN.
891 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000892 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000893 bool isAddrMode5() const {
Jim Grosbach681460f2011-11-01 01:24:45 +0000894 // If we have an immediate that's not a constant, treat it as a label
895 // reference needing a fixup. If it is a constant, it's something else
896 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000897 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach681460f2011-11-01 01:24:45 +0000898 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000899 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000900 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000901 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000902 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000903 if (!Memory.OffsetImm) return true;
904 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000905 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbach681460f2011-11-01 01:24:45 +0000906 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000907 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000908 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000909 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000910 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000911 return false;
912 return true;
913 }
914 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000915 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000916 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
917 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000918 return false;
919 return true;
920 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000921 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000922 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000923 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000924 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000925 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000926 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000927 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
928 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000929 return false;
930 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000931 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000932 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000933 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000934 return false;
935 return true;
936 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000937 bool isMemThumbRR() const {
938 // Thumb reg+reg addressing is simple. Just two registers, a base and
939 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000940 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000941 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000942 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000943 return isARMLowRegister(Memory.BaseRegNum) &&
944 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000945 }
946 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000947 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000948 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000949 return false;
950 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000951 if (!Memory.OffsetImm) return true;
952 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000953 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
954 }
Jim Grosbach38466302011-08-19 18:55:51 +0000955 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000956 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000957 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000958 return false;
959 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000960 if (!Memory.OffsetImm) return true;
961 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +0000962 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
963 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000964 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000965 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000966 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000967 return false;
968 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000969 if (!Memory.OffsetImm) return true;
970 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000971 return Val >= 0 && Val <= 31;
972 }
Jim Grosbachecd85892011-08-19 18:13:48 +0000973 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000974 if (!isMemory() || Memory.OffsetRegNum != 0 ||
975 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +0000976 return false;
977 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000978 if (!Memory.OffsetImm) return true;
979 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000980 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000981 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000982 bool isMemImm8s4Offset() const {
Jim Grosbach2f196742011-12-19 23:06:24 +0000983 // If we have an immediate that's not a constant, treat it as a label
984 // reference needing a fixup. If it is a constant, it's something else
985 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000986 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach2f196742011-12-19 23:06:24 +0000987 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000988 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000989 return false;
990 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000991 if (!Memory.OffsetImm) return true;
992 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +0000993 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
994 }
Jim Grosbachb6aed502011-09-09 18:37:27 +0000995 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000996 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +0000997 return false;
998 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000999 if (!Memory.OffsetImm) return true;
1000 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +00001001 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
1002 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001003 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001004 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001005 return false;
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001006 // Base reg of PC isn't allowed for these encodings.
1007 if (Memory.BaseRegNum == ARM::PC) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001008 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001009 if (!Memory.OffsetImm) return true;
1010 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +00001011 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001012 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001013 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001014 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001015 return false;
1016 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001017 if (!Memory.OffsetImm) return true;
1018 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001019 return Val >= 0 && Val < 256;
1020 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001021 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001022 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001023 return false;
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001024 // Base reg of PC isn't allowed for these encodings.
1025 if (Memory.BaseRegNum == ARM::PC) return false;
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001026 // Immediate offset in range [-255, -1].
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001027 if (!Memory.OffsetImm) return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001028 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001029 return (Val == INT32_MIN) || (Val > -256 && Val < 0);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001030 }
1031 bool isMemUImm12Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001032 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001033 return false;
1034 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001035 if (!Memory.OffsetImm) return true;
1036 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001037 return (Val >= 0 && Val < 4096);
1038 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001039 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +00001040 // If we have an immediate that's not a constant, treat it as a label
1041 // reference needing a fixup. If it is a constant, it's something else
1042 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001043 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +00001044 return true;
1045
Jim Grosbach57dcb852011-10-11 17:29:55 +00001046 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001047 return false;
1048 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001049 if (!Memory.OffsetImm) return true;
1050 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +00001051 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001052 }
1053 bool isPostIdxImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001054 if (!isImm()) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001055 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1056 if (!CE) return false;
1057 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +00001058 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001059 }
Jim Grosbach2bd01182011-10-11 21:55:36 +00001060 bool isPostIdxImm8s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001061 if (!isImm()) return false;
Jim Grosbach2bd01182011-10-11 21:55:36 +00001062 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1063 if (!CE) return false;
1064 int64_t Val = CE->getValue();
1065 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1066 (Val == INT32_MIN);
1067 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001068
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001069 bool isMSRMask() const { return Kind == k_MSRMask; }
1070 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001071
Jim Grosbach0e387b22011-10-17 22:26:03 +00001072 // NEON operands.
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001073 bool isSingleSpacedVectorList() const {
1074 return Kind == k_VectorList && !VectorList.isDoubleSpaced;
1075 }
1076 bool isDoubleSpacedVectorList() const {
1077 return Kind == k_VectorList && VectorList.isDoubleSpaced;
1078 }
Jim Grosbach862019c2011-10-18 23:02:30 +00001079 bool isVecListOneD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001080 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach862019c2011-10-18 23:02:30 +00001081 return VectorList.Count == 1;
1082 }
1083
Jim Grosbach280dfad2011-10-21 18:54:25 +00001084 bool isVecListTwoD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001085 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach280dfad2011-10-21 18:54:25 +00001086 return VectorList.Count == 2;
1087 }
1088
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001089 bool isVecListThreeD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001090 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001091 return VectorList.Count == 3;
1092 }
1093
Jim Grosbachb6310312011-10-21 20:35:01 +00001094 bool isVecListFourD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001095 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachb6310312011-10-21 20:35:01 +00001096 return VectorList.Count == 4;
1097 }
1098
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001099 bool isVecListTwoQ() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001100 if (!isDoubleSpacedVectorList()) return false;
1101 return VectorList.Count == 2;
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001102 }
1103
Jim Grosbachc387fc62012-01-23 23:20:46 +00001104 bool isVecListThreeQ() const {
1105 if (!isDoubleSpacedVectorList()) return false;
1106 return VectorList.Count == 3;
1107 }
1108
Jim Grosbach7945ead2012-01-24 00:43:12 +00001109 bool isVecListFourQ() const {
1110 if (!isDoubleSpacedVectorList()) return false;
1111 return VectorList.Count == 4;
1112 }
1113
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001114 bool isSingleSpacedVectorAllLanes() const {
1115 return Kind == k_VectorListAllLanes && !VectorList.isDoubleSpaced;
1116 }
1117 bool isDoubleSpacedVectorAllLanes() const {
1118 return Kind == k_VectorListAllLanes && VectorList.isDoubleSpaced;
1119 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00001120 bool isVecListOneDAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001121 if (!isSingleSpacedVectorAllLanes()) return false;
Jim Grosbach98b05a52011-11-30 01:09:44 +00001122 return VectorList.Count == 1;
1123 }
1124
Jim Grosbach13af2222011-11-30 18:21:25 +00001125 bool isVecListTwoDAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001126 if (!isSingleSpacedVectorAllLanes()) return false;
1127 return VectorList.Count == 2;
1128 }
1129
1130 bool isVecListTwoQAllLanes() const {
1131 if (!isDoubleSpacedVectorAllLanes()) return false;
Jim Grosbach13af2222011-11-30 18:21:25 +00001132 return VectorList.Count == 2;
1133 }
1134
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001135 bool isSingleSpacedVectorIndexed() const {
1136 return Kind == k_VectorListIndexed && !VectorList.isDoubleSpaced;
1137 }
1138 bool isDoubleSpacedVectorIndexed() const {
1139 return Kind == k_VectorListIndexed && VectorList.isDoubleSpaced;
1140 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00001141 bool isVecListOneDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001142 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach7636bf62011-12-02 00:35:16 +00001143 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1144 }
1145
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001146 bool isVecListOneDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001147 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001148 return VectorList.Count == 1 && VectorList.LaneIndex <= 3;
1149 }
1150
1151 bool isVecListOneDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001152 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001153 return VectorList.Count == 1 && VectorList.LaneIndex <= 1;
1154 }
1155
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001156 bool isVecListTwoDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001157 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001158 return VectorList.Count == 2 && VectorList.LaneIndex <= 7;
1159 }
1160
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001161 bool isVecListTwoDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001162 if (!isSingleSpacedVectorIndexed()) return false;
1163 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1164 }
1165
1166 bool isVecListTwoQWordIndexed() const {
1167 if (!isDoubleSpacedVectorIndexed()) return false;
1168 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1169 }
1170
1171 bool isVecListTwoQHWordIndexed() const {
1172 if (!isDoubleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001173 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1174 }
1175
1176 bool isVecListTwoDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001177 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001178 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1179 }
1180
Jim Grosbach3a678af2012-01-23 21:53:26 +00001181 bool isVecListThreeDByteIndexed() const {
1182 if (!isSingleSpacedVectorIndexed()) return false;
1183 return VectorList.Count == 3 && VectorList.LaneIndex <= 7;
1184 }
1185
1186 bool isVecListThreeDHWordIndexed() const {
1187 if (!isSingleSpacedVectorIndexed()) return false;
1188 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1189 }
1190
1191 bool isVecListThreeQWordIndexed() const {
1192 if (!isDoubleSpacedVectorIndexed()) return false;
1193 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1194 }
1195
1196 bool isVecListThreeQHWordIndexed() const {
1197 if (!isDoubleSpacedVectorIndexed()) return false;
1198 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1199 }
1200
1201 bool isVecListThreeDWordIndexed() const {
1202 if (!isSingleSpacedVectorIndexed()) return false;
1203 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1204 }
1205
Jim Grosbach460a9052011-10-07 23:56:00 +00001206 bool isVectorIndex8() const {
1207 if (Kind != k_VectorIndex) return false;
1208 return VectorIndex.Val < 8;
1209 }
1210 bool isVectorIndex16() const {
1211 if (Kind != k_VectorIndex) return false;
1212 return VectorIndex.Val < 4;
1213 }
1214 bool isVectorIndex32() const {
1215 if (Kind != k_VectorIndex) return false;
1216 return VectorIndex.Val < 2;
1217 }
1218
Jim Grosbach0e387b22011-10-17 22:26:03 +00001219 bool isNEONi8splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001220 if (!isImm()) return false;
Jim Grosbach0e387b22011-10-17 22:26:03 +00001221 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1222 // Must be a constant.
1223 if (!CE) return false;
1224 int64_t Value = CE->getValue();
1225 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1226 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +00001227 return Value >= 0 && Value < 256;
1228 }
Jim Grosbach460a9052011-10-07 23:56:00 +00001229
Jim Grosbachea461102011-10-17 23:09:09 +00001230 bool isNEONi16splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001231 if (!isImm()) return false;
Jim Grosbachea461102011-10-17 23:09:09 +00001232 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1233 // Must be a constant.
1234 if (!CE) return false;
1235 int64_t Value = CE->getValue();
1236 // i16 value in the range [0,255] or [0x0100, 0xff00]
1237 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1238 }
1239
Jim Grosbach6248a542011-10-18 00:22:00 +00001240 bool isNEONi32splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001241 if (!isImm()) return false;
Jim Grosbach6248a542011-10-18 00:22:00 +00001242 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1243 // Must be a constant.
1244 if (!CE) return false;
1245 int64_t Value = CE->getValue();
1246 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1247 return (Value >= 0 && Value < 256) ||
1248 (Value >= 0x0100 && Value <= 0xff00) ||
1249 (Value >= 0x010000 && Value <= 0xff0000) ||
1250 (Value >= 0x01000000 && Value <= 0xff000000);
1251 }
1252
1253 bool isNEONi32vmov() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001254 if (!isImm()) return false;
Jim Grosbach6248a542011-10-18 00:22:00 +00001255 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1256 // Must be a constant.
1257 if (!CE) return false;
1258 int64_t Value = CE->getValue();
1259 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1260 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1261 return (Value >= 0 && Value < 256) ||
1262 (Value >= 0x0100 && Value <= 0xff00) ||
1263 (Value >= 0x010000 && Value <= 0xff0000) ||
1264 (Value >= 0x01000000 && Value <= 0xff000000) ||
1265 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1266 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1267 }
Jim Grosbach9b087852011-12-19 23:51:07 +00001268 bool isNEONi32vmovNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001269 if (!isImm()) return false;
Jim Grosbach9b087852011-12-19 23:51:07 +00001270 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1271 // Must be a constant.
1272 if (!CE) return false;
1273 int64_t Value = ~CE->getValue();
1274 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1275 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1276 return (Value >= 0 && Value < 256) ||
1277 (Value >= 0x0100 && Value <= 0xff00) ||
1278 (Value >= 0x010000 && Value <= 0xff0000) ||
1279 (Value >= 0x01000000 && Value <= 0xff000000) ||
1280 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1281 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1282 }
Jim Grosbach6248a542011-10-18 00:22:00 +00001283
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001284 bool isNEONi64splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001285 if (!isImm()) return false;
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001286 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1287 // Must be a constant.
1288 if (!CE) return false;
1289 uint64_t Value = CE->getValue();
1290 // i64 value with each byte being either 0 or 0xff.
1291 for (unsigned i = 0; i < 8; ++i)
1292 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1293 return true;
1294 }
1295
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001296 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001297 // Add as immediates when possible. Null MCExpr = 0.
1298 if (Expr == 0)
1299 Inst.addOperand(MCOperand::CreateImm(0));
1300 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001301 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1302 else
1303 Inst.addOperand(MCOperand::CreateExpr(Expr));
1304 }
1305
Daniel Dunbar8462b302010-08-11 06:36:53 +00001306 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001307 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001308 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001309 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1310 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001311 }
1312
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001313 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1314 assert(N == 1 && "Invalid number of operands!");
1315 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1316 }
1317
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001318 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1319 assert(N == 1 && "Invalid number of operands!");
1320 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1321 }
1322
1323 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1324 assert(N == 1 && "Invalid number of operands!");
1325 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1326 }
1327
Jim Grosbach89df9962011-08-26 21:43:41 +00001328 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1329 assert(N == 1 && "Invalid number of operands!");
1330 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1331 }
1332
1333 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1334 assert(N == 1 && "Invalid number of operands!");
1335 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1336 }
1337
Jim Grosbachd67641b2010-12-06 18:21:12 +00001338 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1339 assert(N == 1 && "Invalid number of operands!");
1340 Inst.addOperand(MCOperand::CreateReg(getReg()));
1341 }
1342
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001343 void addRegOperands(MCInst &Inst, unsigned N) const {
1344 assert(N == 1 && "Invalid number of operands!");
1345 Inst.addOperand(MCOperand::CreateReg(getReg()));
1346 }
1347
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001348 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001349 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001350 assert(isRegShiftedReg() &&
1351 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001352 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1353 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001354 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001355 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001356 }
1357
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001358 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001359 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001360 assert(isRegShiftedImm() &&
1361 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001362 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001363 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001364 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001365 }
1366
Jim Grosbach580f4a92011-07-25 22:20:28 +00001367 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001368 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001369 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1370 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001371 }
1372
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001373 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001374 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001375 const SmallVectorImpl<unsigned> &RegList = getRegList();
1376 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001377 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1378 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001379 }
1380
Bill Wendling0f630752010-11-17 04:32:08 +00001381 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1382 addRegListOperands(Inst, N);
1383 }
1384
1385 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1386 addRegListOperands(Inst, N);
1387 }
1388
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001389 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1390 assert(N == 1 && "Invalid number of operands!");
1391 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1392 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1393 }
1394
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001395 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1396 assert(N == 1 && "Invalid number of operands!");
1397 // Munge the lsb/width into a bitfield mask.
1398 unsigned lsb = Bitfield.LSB;
1399 unsigned width = Bitfield.Width;
1400 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1401 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1402 (32 - (lsb + width)));
1403 Inst.addOperand(MCOperand::CreateImm(Mask));
1404 }
1405
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001406 void addImmOperands(MCInst &Inst, unsigned N) const {
1407 assert(N == 1 && "Invalid number of operands!");
1408 addExpr(Inst, getImm());
1409 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001410
Jim Grosbach4050bc42011-12-22 22:19:05 +00001411 void addFBits16Operands(MCInst &Inst, unsigned N) const {
1412 assert(N == 1 && "Invalid number of operands!");
1413 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1414 Inst.addOperand(MCOperand::CreateImm(16 - CE->getValue()));
1415 }
1416
1417 void addFBits32Operands(MCInst &Inst, unsigned N) const {
1418 assert(N == 1 && "Invalid number of operands!");
1419 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1420 Inst.addOperand(MCOperand::CreateImm(32 - CE->getValue()));
1421 }
1422
Jim Grosbach9d390362011-10-03 23:38:36 +00001423 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1424 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach51222d12012-01-20 18:09:51 +00001425 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1426 int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
1427 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach9d390362011-10-03 23:38:36 +00001428 }
1429
Jim Grosbacha77295d2011-09-08 22:07:06 +00001430 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1431 assert(N == 1 && "Invalid number of operands!");
1432 // FIXME: We really want to scale the value here, but the LDRD/STRD
1433 // instruction don't encode operands that way yet.
1434 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1435 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1436 }
1437
Jim Grosbach72f39f82011-08-24 21:22:15 +00001438 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1439 assert(N == 1 && "Invalid number of operands!");
1440 // The immediate is scaled by four in the encoding and is stored
1441 // in the MCInst as such. Lop off the low two bits here.
1442 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1443 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1444 }
1445
1446 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1447 assert(N == 1 && "Invalid number of operands!");
1448 // The immediate is scaled by four in the encoding and is stored
1449 // in the MCInst as such. Lop off the low two bits here.
1450 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1451 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1452 }
1453
Jim Grosbachf4943352011-07-25 23:09:14 +00001454 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1455 assert(N == 1 && "Invalid number of operands!");
1456 // The constant encodes as the immediate-1, and we store in the instruction
1457 // the bits as encoded, so subtract off one here.
1458 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1459 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1460 }
1461
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001462 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1463 assert(N == 1 && "Invalid number of operands!");
1464 // The constant encodes as the immediate-1, and we store in the instruction
1465 // the bits as encoded, so subtract off one here.
1466 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1467 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1468 }
1469
Jim Grosbach70939ee2011-08-17 21:51:27 +00001470 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1471 assert(N == 1 && "Invalid number of operands!");
1472 // The constant encodes as the immediate, except for 32, which encodes as
1473 // zero.
1474 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1475 unsigned Imm = CE->getValue();
1476 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1477 }
1478
Jim Grosbachf6c05252011-07-21 17:23:04 +00001479 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1480 assert(N == 1 && "Invalid number of operands!");
1481 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1482 // the instruction as well.
1483 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1484 int Val = CE->getValue();
1485 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1486 }
1487
Jim Grosbach89a63372011-10-28 22:36:30 +00001488 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1489 assert(N == 1 && "Invalid number of operands!");
1490 // The operand is actually a t2_so_imm, but we have its bitwise
1491 // negation in the assembly source, so twiddle it here.
1492 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1493 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1494 }
1495
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001496 void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1497 assert(N == 1 && "Invalid number of operands!");
1498 // The operand is actually a t2_so_imm, but we have its
1499 // negation in the assembly source, so twiddle it here.
1500 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1501 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1502 }
1503
Jim Grosbache70ec842011-10-28 22:50:54 +00001504 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1505 assert(N == 1 && "Invalid number of operands!");
1506 // The operand is actually a so_imm, but we have its bitwise
1507 // negation in the assembly source, so twiddle it here.
1508 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1509 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1510 }
1511
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001512 void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
1513 assert(N == 1 && "Invalid number of operands!");
1514 // The operand is actually a so_imm, but we have its
1515 // negation in the assembly source, so twiddle it here.
1516 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1517 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1518 }
1519
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001520 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1521 assert(N == 1 && "Invalid number of operands!");
1522 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1523 }
1524
Jim Grosbach7ce05792011-08-03 23:50:40 +00001525 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1526 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001527 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001528 }
1529
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001530 void addMemPCRelImm12Operands(MCInst &Inst, unsigned N) const {
1531 assert(N == 1 && "Invalid number of operands!");
1532 int32_t Imm = Memory.OffsetImm->getValue();
1533 // FIXME: Handle #-0
1534 if (Imm == INT32_MIN) Imm = 0;
1535 Inst.addOperand(MCOperand::CreateImm(Imm));
1536 }
1537
Jim Grosbach57dcb852011-10-11 17:29:55 +00001538 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1539 assert(N == 2 && "Invalid number of operands!");
1540 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1541 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1542 }
1543
Jim Grosbach7ce05792011-08-03 23:50:40 +00001544 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1545 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001546 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1547 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001548 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1549 // Special case for #-0
1550 if (Val == INT32_MIN) Val = 0;
1551 if (Val < 0) Val = -Val;
1552 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1553 } else {
1554 // For register offset, we encode the shift type and negation flag
1555 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001556 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1557 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001558 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001559 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1560 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001561 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001562 }
1563
Jim Grosbach039c2e12011-08-04 23:01:30 +00001564 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1565 assert(N == 2 && "Invalid number of operands!");
1566 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1567 assert(CE && "non-constant AM2OffsetImm operand!");
1568 int32_t Val = CE->getValue();
1569 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1570 // Special case for #-0
1571 if (Val == INT32_MIN) Val = 0;
1572 if (Val < 0) Val = -Val;
1573 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1574 Inst.addOperand(MCOperand::CreateReg(0));
1575 Inst.addOperand(MCOperand::CreateImm(Val));
1576 }
1577
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001578 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1579 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001580 // If we have an immediate that's not a constant, treat it as a label
1581 // reference needing a fixup. If it is a constant, it's something else
1582 // and we reject it.
1583 if (isImm()) {
1584 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1585 Inst.addOperand(MCOperand::CreateReg(0));
1586 Inst.addOperand(MCOperand::CreateImm(0));
1587 return;
1588 }
1589
Jim Grosbache53c87b2011-10-11 15:59:20 +00001590 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1591 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001592 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1593 // Special case for #-0
1594 if (Val == INT32_MIN) Val = 0;
1595 if (Val < 0) Val = -Val;
1596 Val = ARM_AM::getAM3Opc(AddSub, Val);
1597 } else {
1598 // For register offset, we encode the shift type and negation flag
1599 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001600 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001601 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001602 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1603 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001604 Inst.addOperand(MCOperand::CreateImm(Val));
1605 }
1606
1607 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1608 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001609 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001610 int32_t Val =
1611 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1612 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1613 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001614 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001615 }
1616
1617 // Constant offset.
1618 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1619 int32_t Val = CE->getValue();
1620 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1621 // Special case for #-0
1622 if (Val == INT32_MIN) Val = 0;
1623 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001624 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001625 Inst.addOperand(MCOperand::CreateReg(0));
1626 Inst.addOperand(MCOperand::CreateImm(Val));
1627 }
1628
Jim Grosbach7ce05792011-08-03 23:50:40 +00001629 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1630 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach681460f2011-11-01 01:24:45 +00001631 // If we have an immediate that's not a constant, treat it as a label
1632 // reference needing a fixup. If it is a constant, it's something else
1633 // and we reject it.
1634 if (isImm()) {
1635 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1636 Inst.addOperand(MCOperand::CreateImm(0));
1637 return;
1638 }
1639
Jim Grosbach7ce05792011-08-03 23:50:40 +00001640 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001641 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001642 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1643 // Special case for #-0
1644 if (Val == INT32_MIN) Val = 0;
1645 if (Val < 0) Val = -Val;
1646 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001647 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001648 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001649 }
1650
Jim Grosbacha77295d2011-09-08 22:07:06 +00001651 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1652 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001653 // If we have an immediate that's not a constant, treat it as a label
1654 // reference needing a fixup. If it is a constant, it's something else
1655 // and we reject it.
1656 if (isImm()) {
1657 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1658 Inst.addOperand(MCOperand::CreateImm(0));
1659 return;
1660 }
1661
Jim Grosbache53c87b2011-10-11 15:59:20 +00001662 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1663 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001664 Inst.addOperand(MCOperand::CreateImm(Val));
1665 }
1666
Jim Grosbachb6aed502011-09-09 18:37:27 +00001667 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1668 assert(N == 2 && "Invalid number of operands!");
1669 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001670 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1671 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001672 Inst.addOperand(MCOperand::CreateImm(Val));
1673 }
1674
Jim Grosbach7ce05792011-08-03 23:50:40 +00001675 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1676 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001677 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1678 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001679 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001680 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001681
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001682 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1683 addMemImm8OffsetOperands(Inst, N);
1684 }
1685
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001686 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001687 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001688 }
1689
1690 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1691 assert(N == 2 && "Invalid number of operands!");
1692 // If this is an immediate, it's a label reference.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001693 if (isImm()) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001694 addExpr(Inst, getImm());
1695 Inst.addOperand(MCOperand::CreateImm(0));
1696 return;
1697 }
1698
1699 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001700 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1701 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001702 Inst.addOperand(MCOperand::CreateImm(Val));
1703 }
1704
Jim Grosbach7ce05792011-08-03 23:50:40 +00001705 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1706 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001707 // If this is an immediate, it's a label reference.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001708 if (isImm()) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001709 addExpr(Inst, getImm());
1710 Inst.addOperand(MCOperand::CreateImm(0));
1711 return;
1712 }
1713
1714 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001715 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1716 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001717 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001718 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001719
Jim Grosbach7f739be2011-09-19 22:21:13 +00001720 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1721 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001722 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1723 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001724 }
1725
1726 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1727 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001728 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1729 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001730 }
1731
Jim Grosbach7ce05792011-08-03 23:50:40 +00001732 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1733 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001734 unsigned Val =
1735 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1736 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001737 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1738 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001739 Inst.addOperand(MCOperand::CreateImm(Val));
1740 }
1741
Jim Grosbachab899c12011-09-07 23:10:15 +00001742 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1743 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001744 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1745 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1746 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001747 }
1748
Jim Grosbach7ce05792011-08-03 23:50:40 +00001749 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1750 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001751 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1752 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001753 }
1754
Jim Grosbach60f91a32011-08-19 17:55:24 +00001755 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1756 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001757 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1758 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001759 Inst.addOperand(MCOperand::CreateImm(Val));
1760 }
1761
Jim Grosbach38466302011-08-19 18:55:51 +00001762 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1763 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001764 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1765 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001766 Inst.addOperand(MCOperand::CreateImm(Val));
1767 }
1768
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001769 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1770 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001771 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1772 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001773 Inst.addOperand(MCOperand::CreateImm(Val));
1774 }
1775
Jim Grosbachecd85892011-08-19 18:13:48 +00001776 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1777 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001778 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1779 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001780 Inst.addOperand(MCOperand::CreateImm(Val));
1781 }
1782
Jim Grosbach7ce05792011-08-03 23:50:40 +00001783 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1784 assert(N == 1 && "Invalid number of operands!");
1785 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1786 assert(CE && "non-constant post-idx-imm8 operand!");
1787 int Imm = CE->getValue();
1788 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001789 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001790 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1791 Inst.addOperand(MCOperand::CreateImm(Imm));
1792 }
1793
Jim Grosbach2bd01182011-10-11 21:55:36 +00001794 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1795 assert(N == 1 && "Invalid number of operands!");
1796 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1797 assert(CE && "non-constant post-idx-imm8s4 operand!");
1798 int Imm = CE->getValue();
1799 bool isAdd = Imm >= 0;
1800 if (Imm == INT32_MIN) Imm = 0;
1801 // Immediate is scaled by 4.
1802 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1803 Inst.addOperand(MCOperand::CreateImm(Imm));
1804 }
1805
Jim Grosbach7ce05792011-08-03 23:50:40 +00001806 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1807 assert(N == 2 && "Invalid number of operands!");
1808 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001809 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1810 }
1811
1812 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1813 assert(N == 2 && "Invalid number of operands!");
1814 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1815 // The sign, shift type, and shift amount are encoded in a single operand
1816 // using the AM2 encoding helpers.
1817 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1818 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1819 PostIdxReg.ShiftTy);
1820 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001821 }
1822
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001823 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1824 assert(N == 1 && "Invalid number of operands!");
1825 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1826 }
1827
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001828 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1829 assert(N == 1 && "Invalid number of operands!");
1830 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1831 }
1832
Jim Grosbach6029b6d2011-11-29 23:51:09 +00001833 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach862019c2011-10-18 23:02:30 +00001834 assert(N == 1 && "Invalid number of operands!");
1835 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1836 }
1837
Jim Grosbach7636bf62011-12-02 00:35:16 +00001838 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1839 assert(N == 2 && "Invalid number of operands!");
1840 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1841 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1842 }
1843
Jim Grosbach460a9052011-10-07 23:56:00 +00001844 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1845 assert(N == 1 && "Invalid number of operands!");
1846 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1847 }
1848
1849 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1850 assert(N == 1 && "Invalid number of operands!");
1851 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1852 }
1853
1854 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1855 assert(N == 1 && "Invalid number of operands!");
1856 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1857 }
1858
Jim Grosbach0e387b22011-10-17 22:26:03 +00001859 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1860 assert(N == 1 && "Invalid number of operands!");
1861 // The immediate encodes the type of constant as well as the value.
1862 // Mask in that this is an i8 splat.
1863 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1864 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1865 }
1866
Jim Grosbachea461102011-10-17 23:09:09 +00001867 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1868 assert(N == 1 && "Invalid number of operands!");
1869 // The immediate encodes the type of constant as well as the value.
1870 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1871 unsigned Value = CE->getValue();
1872 if (Value >= 256)
1873 Value = (Value >> 8) | 0xa00;
1874 else
1875 Value |= 0x800;
1876 Inst.addOperand(MCOperand::CreateImm(Value));
1877 }
1878
Jim Grosbach6248a542011-10-18 00:22:00 +00001879 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1880 assert(N == 1 && "Invalid number of operands!");
1881 // The immediate encodes the type of constant as well as the value.
1882 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1883 unsigned Value = CE->getValue();
1884 if (Value >= 256 && Value <= 0xff00)
1885 Value = (Value >> 8) | 0x200;
1886 else if (Value > 0xffff && Value <= 0xff0000)
1887 Value = (Value >> 16) | 0x400;
1888 else if (Value > 0xffffff)
1889 Value = (Value >> 24) | 0x600;
1890 Inst.addOperand(MCOperand::CreateImm(Value));
1891 }
1892
1893 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1894 assert(N == 1 && "Invalid number of operands!");
1895 // The immediate encodes the type of constant as well as the value.
1896 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1897 unsigned Value = CE->getValue();
1898 if (Value >= 256 && Value <= 0xffff)
1899 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1900 else if (Value > 0xffff && Value <= 0xffffff)
1901 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1902 else if (Value > 0xffffff)
1903 Value = (Value >> 24) | 0x600;
1904 Inst.addOperand(MCOperand::CreateImm(Value));
1905 }
1906
Jim Grosbach9b087852011-12-19 23:51:07 +00001907 void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const {
1908 assert(N == 1 && "Invalid number of operands!");
1909 // The immediate encodes the type of constant as well as the value.
1910 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1911 unsigned Value = ~CE->getValue();
1912 if (Value >= 256 && Value <= 0xffff)
1913 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1914 else if (Value > 0xffff && Value <= 0xffffff)
1915 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1916 else if (Value > 0xffffff)
1917 Value = (Value >> 24) | 0x600;
1918 Inst.addOperand(MCOperand::CreateImm(Value));
1919 }
1920
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001921 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1922 assert(N == 1 && "Invalid number of operands!");
1923 // The immediate encodes the type of constant as well as the value.
1924 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1925 uint64_t Value = CE->getValue();
1926 unsigned Imm = 0;
1927 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1928 Imm |= (Value & 1) << i;
1929 }
1930 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1931 }
1932
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001933 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001934
Jim Grosbach89df9962011-08-26 21:43:41 +00001935 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001936 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001937 Op->ITMask.Mask = Mask;
1938 Op->StartLoc = S;
1939 Op->EndLoc = S;
1940 return Op;
1941 }
1942
Chris Lattner3a697562010-10-28 17:20:03 +00001943 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001944 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001945 Op->CC.Val = CC;
1946 Op->StartLoc = S;
1947 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001948 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001949 }
1950
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001951 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001952 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001953 Op->Cop.Val = CopVal;
1954 Op->StartLoc = S;
1955 Op->EndLoc = S;
1956 return Op;
1957 }
1958
1959 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001960 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001961 Op->Cop.Val = CopVal;
1962 Op->StartLoc = S;
1963 Op->EndLoc = S;
1964 return Op;
1965 }
1966
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001967 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1968 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1969 Op->Cop.Val = Val;
1970 Op->StartLoc = S;
1971 Op->EndLoc = E;
1972 return Op;
1973 }
1974
Jim Grosbachd67641b2010-12-06 18:21:12 +00001975 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001976 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00001977 Op->Reg.RegNum = RegNum;
1978 Op->StartLoc = S;
1979 Op->EndLoc = S;
1980 return Op;
1981 }
1982
Chris Lattner3a697562010-10-28 17:20:03 +00001983 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001984 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00001985 Op->Tok.Data = Str.data();
1986 Op->Tok.Length = Str.size();
1987 Op->StartLoc = S;
1988 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001989 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001990 }
1991
Bill Wendling50d0f582010-11-18 23:43:05 +00001992 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001993 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00001994 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001995 Op->StartLoc = S;
1996 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001997 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001998 }
1999
Jim Grosbache8606dc2011-07-13 17:50:29 +00002000 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
2001 unsigned SrcReg,
2002 unsigned ShiftReg,
2003 unsigned ShiftImm,
2004 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002005 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002006 Op->RegShiftedReg.ShiftTy = ShTy;
2007 Op->RegShiftedReg.SrcReg = SrcReg;
2008 Op->RegShiftedReg.ShiftReg = ShiftReg;
2009 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002010 Op->StartLoc = S;
2011 Op->EndLoc = E;
2012 return Op;
2013 }
2014
Owen Anderson92a20222011-07-21 18:54:16 +00002015 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
2016 unsigned SrcReg,
2017 unsigned ShiftImm,
2018 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002019 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002020 Op->RegShiftedImm.ShiftTy = ShTy;
2021 Op->RegShiftedImm.SrcReg = SrcReg;
2022 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00002023 Op->StartLoc = S;
2024 Op->EndLoc = E;
2025 return Op;
2026 }
2027
Jim Grosbach580f4a92011-07-25 22:20:28 +00002028 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002029 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002030 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00002031 Op->ShifterImm.isASR = isASR;
2032 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00002033 Op->StartLoc = S;
2034 Op->EndLoc = E;
2035 return Op;
2036 }
2037
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002038 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002039 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002040 Op->RotImm.Imm = Imm;
2041 Op->StartLoc = S;
2042 Op->EndLoc = E;
2043 return Op;
2044 }
2045
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002046 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
2047 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002048 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002049 Op->Bitfield.LSB = LSB;
2050 Op->Bitfield.Width = Width;
2051 Op->StartLoc = S;
2052 Op->EndLoc = E;
2053 return Op;
2054 }
2055
Bill Wendling7729e062010-11-09 22:44:22 +00002056 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00002057 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002058 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002059 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002060
Jim Grosbachd300b942011-09-13 22:56:44 +00002061 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002062 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00002063 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00002064 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002065 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002066
2067 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00002068 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002069 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00002070 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00002071 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002072 Op->StartLoc = StartLoc;
2073 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00002074 return Op;
2075 }
2076
Jim Grosbach862019c2011-10-18 23:02:30 +00002077 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002078 bool isDoubleSpaced, SMLoc S, SMLoc E) {
Jim Grosbach862019c2011-10-18 23:02:30 +00002079 ARMOperand *Op = new ARMOperand(k_VectorList);
2080 Op->VectorList.RegNum = RegNum;
2081 Op->VectorList.Count = Count;
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002082 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach862019c2011-10-18 23:02:30 +00002083 Op->StartLoc = S;
2084 Op->EndLoc = E;
2085 return Op;
2086 }
2087
Jim Grosbach98b05a52011-11-30 01:09:44 +00002088 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002089 bool isDoubleSpaced,
Jim Grosbach98b05a52011-11-30 01:09:44 +00002090 SMLoc S, SMLoc E) {
2091 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
2092 Op->VectorList.RegNum = RegNum;
2093 Op->VectorList.Count = Count;
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002094 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002095 Op->StartLoc = S;
2096 Op->EndLoc = E;
2097 return Op;
2098 }
2099
Jim Grosbach7636bf62011-12-02 00:35:16 +00002100 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002101 unsigned Index,
2102 bool isDoubleSpaced,
2103 SMLoc S, SMLoc E) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002104 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
2105 Op->VectorList.RegNum = RegNum;
2106 Op->VectorList.Count = Count;
2107 Op->VectorList.LaneIndex = Index;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002108 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002109 Op->StartLoc = S;
2110 Op->EndLoc = E;
2111 return Op;
2112 }
2113
Jim Grosbach460a9052011-10-07 23:56:00 +00002114 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
2115 MCContext &Ctx) {
2116 ARMOperand *Op = new ARMOperand(k_VectorIndex);
2117 Op->VectorIndex.Val = Idx;
2118 Op->StartLoc = S;
2119 Op->EndLoc = E;
2120 return Op;
2121 }
2122
Chris Lattner3a697562010-10-28 17:20:03 +00002123 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002124 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00002125 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00002126 Op->StartLoc = S;
2127 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002128 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00002129 }
2130
Jim Grosbach7ce05792011-08-03 23:50:40 +00002131 static ARMOperand *CreateMem(unsigned BaseRegNum,
2132 const MCConstantExpr *OffsetImm,
2133 unsigned OffsetRegNum,
2134 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002135 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00002136 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002137 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00002138 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002139 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00002140 Op->Memory.BaseRegNum = BaseRegNum;
2141 Op->Memory.OffsetImm = OffsetImm;
2142 Op->Memory.OffsetRegNum = OffsetRegNum;
2143 Op->Memory.ShiftType = ShiftType;
2144 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00002145 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00002146 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002147 Op->StartLoc = S;
2148 Op->EndLoc = E;
2149 return Op;
2150 }
Jim Grosbach16c74252010-10-29 14:46:02 +00002151
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002152 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
2153 ARM_AM::ShiftOpc ShiftTy,
2154 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002155 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002156 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002157 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002158 Op->PostIdxReg.isAdd = isAdd;
2159 Op->PostIdxReg.ShiftTy = ShiftTy;
2160 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00002161 Op->StartLoc = S;
2162 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002163 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002164 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002165
2166 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002167 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002168 Op->MBOpt.Val = Opt;
2169 Op->StartLoc = S;
2170 Op->EndLoc = S;
2171 return Op;
2172 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002173
2174 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002175 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002176 Op->IFlags.Val = IFlags;
2177 Op->StartLoc = S;
2178 Op->EndLoc = S;
2179 return Op;
2180 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002181
2182 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002183 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002184 Op->MMask.Val = MMask;
2185 Op->StartLoc = S;
2186 Op->EndLoc = S;
2187 return Op;
2188 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002189};
2190
2191} // end anonymous namespace.
2192
Jim Grosbachb7f689b2011-07-13 15:34:57 +00002193void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002194 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002195 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00002196 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002197 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002198 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00002199 OS << "<ccout " << getReg() << ">";
2200 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002201 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002202 static const char *MaskStr[] = {
2203 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2204 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2205 };
Jim Grosbach89df9962011-08-26 21:43:41 +00002206 assert((ITMask.Mask & 0xf) == ITMask.Mask);
2207 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2208 break;
2209 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002210 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002211 OS << "<coprocessor number: " << getCoproc() << ">";
2212 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002213 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002214 OS << "<coprocessor register: " << getCoproc() << ">";
2215 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002216 case k_CoprocOption:
2217 OS << "<coprocessor option: " << CoprocOption.Val << ">";
2218 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002219 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002220 OS << "<mask: " << getMSRMask() << ">";
2221 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002222 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002223 getImm()->print(OS);
2224 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002225 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002226 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2227 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002228 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002229 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00002230 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002231 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002232 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002233 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002234 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2235 << PostIdxReg.RegNum;
2236 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2237 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2238 << PostIdxReg.ShiftImm;
2239 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00002240 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002241 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002242 OS << "<ARM_PROC::";
2243 unsigned IFlags = getProcIFlags();
2244 for (int i=2; i >= 0; --i)
2245 if (IFlags & (1 << i))
2246 OS << ARM_PROC::IFlagsToString(1 << i);
2247 OS << ">";
2248 break;
2249 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002250 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00002251 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002252 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002253 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00002254 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2255 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00002256 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002257 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00002258 OS << "<so_reg_reg "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002259 << RegShiftedReg.SrcReg << " "
2260 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2261 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson00828302011-03-18 22:50:18 +00002262 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002263 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00002264 OS << "<so_reg_imm "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002265 << RegShiftedImm.SrcReg << " "
2266 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2267 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Anderson92a20222011-07-21 18:54:16 +00002268 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002269 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002270 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2271 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002272 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002273 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2274 << ", width: " << Bitfield.Width << ">";
2275 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002276 case k_RegisterList:
2277 case k_DPRRegisterList:
2278 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00002279 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002280
Bill Wendling5fa22a12010-11-09 23:28:44 +00002281 const SmallVectorImpl<unsigned> &RegList = getRegList();
2282 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002283 I = RegList.begin(), E = RegList.end(); I != E; ) {
2284 OS << *I;
2285 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002286 }
2287
2288 OS << ">";
2289 break;
2290 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002291 case k_VectorList:
2292 OS << "<vector_list " << VectorList.Count << " * "
2293 << VectorList.RegNum << ">";
2294 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002295 case k_VectorListAllLanes:
2296 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2297 << VectorList.RegNum << ">";
2298 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002299 case k_VectorListIndexed:
2300 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2301 << VectorList.Count << " * " << VectorList.RegNum << ">";
2302 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002303 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002304 OS << "'" << getToken() << "'";
2305 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00002306 case k_VectorIndex:
2307 OS << "<vectorindex " << getVectorIndex() << ">";
2308 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002309 }
2310}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00002311
2312/// @name Auto-generated Match Functions
2313/// {
2314
2315static unsigned MatchRegisterName(StringRef Name);
2316
2317/// }
2318
Bob Wilson69df7232011-02-03 21:46:10 +00002319bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2320 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbacha39cda72011-12-14 02:16:11 +00002321 StartLoc = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002322 RegNo = tryParseRegister();
Jim Grosbacha39cda72011-12-14 02:16:11 +00002323 EndLoc = Parser.getTok().getLoc();
Roman Divackybf755322011-01-27 17:14:22 +00002324
2325 return (RegNo == (unsigned)-1);
2326}
2327
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002328/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002329/// and if it is a register name the token is eaten and the register number is
2330/// returned. Otherwise return -1.
2331///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002332int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002333 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002334 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002335
Benjamin Kramer59085362011-11-06 20:37:06 +00002336 std::string lowerCase = Tok.getString().lower();
Owen Anderson0c9f2502011-01-13 22:50:36 +00002337 unsigned RegNum = MatchRegisterName(lowerCase);
2338 if (!RegNum) {
2339 RegNum = StringSwitch<unsigned>(lowerCase)
2340 .Case("r13", ARM::SP)
2341 .Case("r14", ARM::LR)
2342 .Case("r15", ARM::PC)
2343 .Case("ip", ARM::R12)
Jim Grosbach40e28552011-12-08 19:27:38 +00002344 // Additional register name aliases for 'gas' compatibility.
2345 .Case("a1", ARM::R0)
2346 .Case("a2", ARM::R1)
2347 .Case("a3", ARM::R2)
2348 .Case("a4", ARM::R3)
2349 .Case("v1", ARM::R4)
2350 .Case("v2", ARM::R5)
2351 .Case("v3", ARM::R6)
2352 .Case("v4", ARM::R7)
2353 .Case("v5", ARM::R8)
2354 .Case("v6", ARM::R9)
2355 .Case("v7", ARM::R10)
2356 .Case("v8", ARM::R11)
2357 .Case("sb", ARM::R9)
2358 .Case("sl", ARM::R10)
2359 .Case("fp", ARM::R11)
Owen Anderson0c9f2502011-01-13 22:50:36 +00002360 .Default(0);
2361 }
Jim Grosbacha39cda72011-12-14 02:16:11 +00002362 if (!RegNum) {
Jim Grosbachaee718b2011-12-20 23:11:00 +00002363 // Check for aliases registered via .req. Canonicalize to lower case.
2364 // That's more consistent since register names are case insensitive, and
2365 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2366 StringMap<unsigned>::const_iterator Entry = RegisterReqs.find(lowerCase);
Jim Grosbacha39cda72011-12-14 02:16:11 +00002367 // If no match, return failure.
2368 if (Entry == RegisterReqs.end())
2369 return -1;
2370 Parser.Lex(); // Eat identifier token.
2371 return Entry->getValue();
2372 }
Bob Wilson69df7232011-02-03 21:46:10 +00002373
Chris Lattnere5658fa2010-10-30 04:09:10 +00002374 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002375
Chris Lattnere5658fa2010-10-30 04:09:10 +00002376 return RegNum;
2377}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002378
Jim Grosbach19906722011-07-13 18:49:30 +00002379// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2380// If a recoverable error occurs, return 1. If an irrecoverable error
2381// occurs, return -1. An irrecoverable error is one where tokens have been
2382// consumed in the process of trying to parse the shifter (i.e., when it is
2383// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002384int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002385 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2386 SMLoc S = Parser.getTok().getLoc();
2387 const AsmToken &Tok = Parser.getTok();
2388 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2389
Benjamin Kramer59085362011-11-06 20:37:06 +00002390 std::string lowerCase = Tok.getString().lower();
Owen Anderson00828302011-03-18 22:50:18 +00002391 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbachaf4edea2011-12-07 23:40:58 +00002392 .Case("asl", ARM_AM::lsl)
Owen Anderson00828302011-03-18 22:50:18 +00002393 .Case("lsl", ARM_AM::lsl)
2394 .Case("lsr", ARM_AM::lsr)
2395 .Case("asr", ARM_AM::asr)
2396 .Case("ror", ARM_AM::ror)
2397 .Case("rrx", ARM_AM::rrx)
2398 .Default(ARM_AM::no_shift);
2399
2400 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002401 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002402
Jim Grosbache8606dc2011-07-13 17:50:29 +00002403 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002404
Jim Grosbache8606dc2011-07-13 17:50:29 +00002405 // The source register for the shift has already been added to the
2406 // operand list, so we need to pop it off and combine it into the shifted
2407 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002408 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002409 if (!PrevOp->isReg())
2410 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2411 int SrcReg = PrevOp->getReg();
2412 int64_t Imm = 0;
2413 int ShiftReg = 0;
2414 if (ShiftTy == ARM_AM::rrx) {
2415 // RRX Doesn't have an explicit shift amount. The encoder expects
2416 // the shift register to be the same as the source register. Seems odd,
2417 // but OK.
2418 ShiftReg = SrcReg;
2419 } else {
2420 // Figure out if this is shifted by a constant or a register (for non-RRX).
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00002421 if (Parser.getTok().is(AsmToken::Hash) ||
2422 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbache8606dc2011-07-13 17:50:29 +00002423 Parser.Lex(); // Eat hash.
2424 SMLoc ImmLoc = Parser.getTok().getLoc();
2425 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002426 if (getParser().ParseExpression(ShiftExpr)) {
2427 Error(ImmLoc, "invalid immediate shift value");
2428 return -1;
2429 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002430 // The expression must be evaluatable as an immediate.
2431 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002432 if (!CE) {
2433 Error(ImmLoc, "invalid immediate shift value");
2434 return -1;
2435 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002436 // Range check the immediate.
2437 // lsl, ror: 0 <= imm <= 31
2438 // lsr, asr: 0 <= imm <= 32
2439 Imm = CE->getValue();
2440 if (Imm < 0 ||
2441 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2442 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002443 Error(ImmLoc, "immediate shift value out of range");
2444 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002445 }
Jim Grosbachde626ad2011-12-22 17:37:00 +00002446 // shift by zero is a nop. Always send it through as lsl.
2447 // ('as' compatibility)
2448 if (Imm == 0)
2449 ShiftTy = ARM_AM::lsl;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002450 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002451 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002452 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002453 if (ShiftReg == -1) {
2454 Error (L, "expected immediate or register in shift operand");
2455 return -1;
2456 }
2457 } else {
2458 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002459 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002460 return -1;
2461 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002462 }
2463
Owen Anderson92a20222011-07-21 18:54:16 +00002464 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2465 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002466 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002467 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002468 else
2469 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2470 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002471
Jim Grosbach19906722011-07-13 18:49:30 +00002472 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002473}
2474
2475
Bill Wendling50d0f582010-11-18 23:43:05 +00002476/// Try to parse a register name. The token must be an Identifier when called.
2477/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2478/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002479///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002480/// TODO this is likely to change to allow different register types and or to
2481/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002482bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002483tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002484 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002485 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002486 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002487 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002488
Bill Wendling50d0f582010-11-18 23:43:05 +00002489 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002490
Chris Lattnere5658fa2010-10-30 04:09:10 +00002491 const AsmToken &ExclaimTok = Parser.getTok();
2492 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002493 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2494 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002495 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002496 return false;
2497 }
2498
2499 // Also check for an index operand. This is only legal for vector registers,
2500 // but that'll get caught OK in operand matching, so we don't need to
2501 // explicitly filter everything else out here.
2502 if (Parser.getTok().is(AsmToken::LBrac)) {
2503 SMLoc SIdx = Parser.getTok().getLoc();
2504 Parser.Lex(); // Eat left bracket token.
2505
2506 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002507 if (getParser().ParseExpression(ImmVal))
2508 return MatchOperand_ParseFail;
2509 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2510 if (!MCE) {
2511 TokError("immediate value expected for vector index");
2512 return MatchOperand_ParseFail;
2513 }
2514
2515 SMLoc E = Parser.getTok().getLoc();
2516 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2517 Error(E, "']' expected");
2518 return MatchOperand_ParseFail;
2519 }
2520
2521 Parser.Lex(); // Eat right bracket token.
2522
2523 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2524 SIdx, E,
2525 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002526 }
2527
Bill Wendling50d0f582010-11-18 23:43:05 +00002528 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002529}
2530
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002531/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2532/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2533/// "c5", ...
2534static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002535 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2536 // but efficient.
2537 switch (Name.size()) {
David Blaikie4d6ccb52012-01-20 21:51:11 +00002538 default: return -1;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002539 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002540 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002541 return -1;
2542 switch (Name[1]) {
2543 default: return -1;
2544 case '0': return 0;
2545 case '1': return 1;
2546 case '2': return 2;
2547 case '3': return 3;
2548 case '4': return 4;
2549 case '5': return 5;
2550 case '6': return 6;
2551 case '7': return 7;
2552 case '8': return 8;
2553 case '9': return 9;
2554 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002555 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002556 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002557 return -1;
2558 switch (Name[2]) {
2559 default: return -1;
2560 case '0': return 10;
2561 case '1': return 11;
2562 case '2': return 12;
2563 case '3': return 13;
2564 case '4': return 14;
2565 case '5': return 15;
2566 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002567 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002568}
2569
Jim Grosbach89df9962011-08-26 21:43:41 +00002570/// parseITCondCode - Try to parse a condition code for an IT instruction.
2571ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2572parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2573 SMLoc S = Parser.getTok().getLoc();
2574 const AsmToken &Tok = Parser.getTok();
2575 if (!Tok.is(AsmToken::Identifier))
2576 return MatchOperand_NoMatch;
2577 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2578 .Case("eq", ARMCC::EQ)
2579 .Case("ne", ARMCC::NE)
2580 .Case("hs", ARMCC::HS)
2581 .Case("cs", ARMCC::HS)
2582 .Case("lo", ARMCC::LO)
2583 .Case("cc", ARMCC::LO)
2584 .Case("mi", ARMCC::MI)
2585 .Case("pl", ARMCC::PL)
2586 .Case("vs", ARMCC::VS)
2587 .Case("vc", ARMCC::VC)
2588 .Case("hi", ARMCC::HI)
2589 .Case("ls", ARMCC::LS)
2590 .Case("ge", ARMCC::GE)
2591 .Case("lt", ARMCC::LT)
2592 .Case("gt", ARMCC::GT)
2593 .Case("le", ARMCC::LE)
2594 .Case("al", ARMCC::AL)
2595 .Default(~0U);
2596 if (CC == ~0U)
2597 return MatchOperand_NoMatch;
2598 Parser.Lex(); // Eat the token.
2599
2600 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2601
2602 return MatchOperand_Success;
2603}
2604
Jim Grosbach43904292011-07-25 20:14:50 +00002605/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002606/// token must be an Identifier when called, and if it is a coprocessor
2607/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002608ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002609parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002610 SMLoc S = Parser.getTok().getLoc();
2611 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002612 if (Tok.isNot(AsmToken::Identifier))
2613 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002614
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002615 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002616 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002617 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002618
2619 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002620 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002621 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002622}
2623
Jim Grosbach43904292011-07-25 20:14:50 +00002624/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002625/// token must be an Identifier when called, and if it is a coprocessor
2626/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002627ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002628parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002629 SMLoc S = Parser.getTok().getLoc();
2630 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002631 if (Tok.isNot(AsmToken::Identifier))
2632 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002633
2634 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2635 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002636 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002637
2638 Parser.Lex(); // Eat identifier token.
2639 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002640 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002641}
2642
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002643/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2644/// coproc_option : '{' imm0_255 '}'
2645ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2646parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2647 SMLoc S = Parser.getTok().getLoc();
2648
2649 // If this isn't a '{', this isn't a coprocessor immediate operand.
2650 if (Parser.getTok().isNot(AsmToken::LCurly))
2651 return MatchOperand_NoMatch;
2652 Parser.Lex(); // Eat the '{'
2653
2654 const MCExpr *Expr;
2655 SMLoc Loc = Parser.getTok().getLoc();
2656 if (getParser().ParseExpression(Expr)) {
2657 Error(Loc, "illegal expression");
2658 return MatchOperand_ParseFail;
2659 }
2660 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2661 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2662 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2663 return MatchOperand_ParseFail;
2664 }
2665 int Val = CE->getValue();
2666
2667 // Check for and consume the closing '}'
2668 if (Parser.getTok().isNot(AsmToken::RCurly))
2669 return MatchOperand_ParseFail;
2670 SMLoc E = Parser.getTok().getLoc();
2671 Parser.Lex(); // Eat the '}'
2672
2673 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2674 return MatchOperand_Success;
2675}
2676
Jim Grosbachd0588e22011-09-14 18:08:35 +00002677// For register list parsing, we need to map from raw GPR register numbering
2678// to the enumeration values. The enumeration values aren't sorted by
2679// register number due to our using "sp", "lr" and "pc" as canonical names.
2680static unsigned getNextRegister(unsigned Reg) {
2681 // If this is a GPR, we need to do it manually, otherwise we can rely
2682 // on the sort ordering of the enumeration since the other reg-classes
2683 // are sane.
2684 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2685 return Reg + 1;
2686 switch(Reg) {
2687 default: assert(0 && "Invalid GPR number!");
2688 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2689 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2690 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2691 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2692 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2693 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2694 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2695 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2696 }
2697}
2698
Jim Grosbachce485e72011-11-11 21:27:40 +00002699// Return the low-subreg of a given Q register.
2700static unsigned getDRegFromQReg(unsigned QReg) {
2701 switch (QReg) {
2702 default: llvm_unreachable("expected a Q register!");
2703 case ARM::Q0: return ARM::D0;
2704 case ARM::Q1: return ARM::D2;
2705 case ARM::Q2: return ARM::D4;
2706 case ARM::Q3: return ARM::D6;
2707 case ARM::Q4: return ARM::D8;
2708 case ARM::Q5: return ARM::D10;
2709 case ARM::Q6: return ARM::D12;
2710 case ARM::Q7: return ARM::D14;
2711 case ARM::Q8: return ARM::D16;
Jim Grosbach25e0a872011-11-15 21:01:30 +00002712 case ARM::Q9: return ARM::D18;
Jim Grosbachce485e72011-11-11 21:27:40 +00002713 case ARM::Q10: return ARM::D20;
2714 case ARM::Q11: return ARM::D22;
2715 case ARM::Q12: return ARM::D24;
2716 case ARM::Q13: return ARM::D26;
2717 case ARM::Q14: return ARM::D28;
2718 case ARM::Q15: return ARM::D30;
2719 }
2720}
2721
Jim Grosbachd0588e22011-09-14 18:08:35 +00002722/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002723bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002724parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002725 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002726 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002727 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002728 Parser.Lex(); // Eat '{' token.
2729 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002730
Jim Grosbachd0588e22011-09-14 18:08:35 +00002731 // Check the first register in the list to see what register class
2732 // this is a list of.
2733 int Reg = tryParseRegister();
2734 if (Reg == -1)
2735 return Error(RegLoc, "register expected");
2736
Jim Grosbachce485e72011-11-11 21:27:40 +00002737 // The reglist instructions have at most 16 registers, so reserve
2738 // space for that many.
2739 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2740
2741 // Allow Q regs and just interpret them as the two D sub-registers.
2742 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2743 Reg = getDRegFromQReg(Reg);
2744 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2745 ++Reg;
2746 }
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002747 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002748 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2749 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2750 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2751 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2752 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2753 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2754 else
2755 return Error(RegLoc, "invalid register in register list");
2756
Jim Grosbachce485e72011-11-11 21:27:40 +00002757 // Store the register.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002758 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002759
Jim Grosbachd0588e22011-09-14 18:08:35 +00002760 // This starts immediately after the first register token in the list,
2761 // so we can see either a comma or a minus (range separator) as a legal
2762 // next token.
2763 while (Parser.getTok().is(AsmToken::Comma) ||
2764 Parser.getTok().is(AsmToken::Minus)) {
2765 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache43862b2011-11-15 23:19:15 +00002766 Parser.Lex(); // Eat the minus.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002767 SMLoc EndLoc = Parser.getTok().getLoc();
2768 int EndReg = tryParseRegister();
2769 if (EndReg == -1)
2770 return Error(EndLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002771 // Allow Q regs and just interpret them as the two D sub-registers.
2772 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2773 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002774 // If the register is the same as the start reg, there's nothing
2775 // more to do.
2776 if (Reg == EndReg)
2777 continue;
2778 // The register must be in the same register class as the first.
2779 if (!RC->contains(EndReg))
2780 return Error(EndLoc, "invalid register in register list");
2781 // Ranges must go from low to high.
2782 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2783 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002784
Jim Grosbachd0588e22011-09-14 18:08:35 +00002785 // Add all the registers in the range to the register list.
2786 while (Reg != EndReg) {
2787 Reg = getNextRegister(Reg);
2788 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2789 }
2790 continue;
2791 }
2792 Parser.Lex(); // Eat the comma.
2793 RegLoc = Parser.getTok().getLoc();
2794 int OldReg = Reg;
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002795 const AsmToken RegTok = Parser.getTok();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002796 Reg = tryParseRegister();
2797 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002798 return Error(RegLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002799 // Allow Q regs and just interpret them as the two D sub-registers.
2800 bool isQReg = false;
2801 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2802 Reg = getDRegFromQReg(Reg);
2803 isQReg = true;
2804 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002805 // The register must be in the same register class as the first.
2806 if (!RC->contains(Reg))
2807 return Error(RegLoc, "invalid register in register list");
2808 // List must be monotonically increasing.
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002809 if (getARMRegisterNumbering(Reg) < getARMRegisterNumbering(OldReg))
Jim Grosbachd0588e22011-09-14 18:08:35 +00002810 return Error(RegLoc, "register list not in ascending order");
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002811 if (getARMRegisterNumbering(Reg) == getARMRegisterNumbering(OldReg)) {
2812 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
2813 ") in register list");
2814 continue;
2815 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002816 // VFP register lists must also be contiguous.
2817 // It's OK to use the enumeration values directly here rather, as the
2818 // VFP register classes have the enum sorted properly.
2819 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2820 Reg != OldReg + 1)
2821 return Error(RegLoc, "non-contiguous register range");
2822 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbachce485e72011-11-11 21:27:40 +00002823 if (isQReg)
2824 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002825 }
2826
Jim Grosbachd0588e22011-09-14 18:08:35 +00002827 SMLoc E = Parser.getTok().getLoc();
2828 if (Parser.getTok().isNot(AsmToken::RCurly))
2829 return Error(E, "'}' expected");
2830 Parser.Lex(); // Eat '}' token.
2831
Jim Grosbach27debd62011-12-13 21:48:29 +00002832 // Push the register list operand.
Bill Wendling50d0f582010-11-18 23:43:05 +00002833 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
Jim Grosbach27debd62011-12-13 21:48:29 +00002834
2835 // The ARM system instruction variants for LDM/STM have a '^' token here.
2836 if (Parser.getTok().is(AsmToken::Caret)) {
2837 Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
2838 Parser.Lex(); // Eat '^' token.
2839 }
2840
Bill Wendling50d0f582010-11-18 23:43:05 +00002841 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002842}
2843
Jim Grosbach98b05a52011-11-30 01:09:44 +00002844// Helper function to parse the lane index for vector lists.
2845ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach7636bf62011-12-02 00:35:16 +00002846parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2847 Index = 0; // Always return a defined index value.
Jim Grosbach98b05a52011-11-30 01:09:44 +00002848 if (Parser.getTok().is(AsmToken::LBrac)) {
2849 Parser.Lex(); // Eat the '['.
2850 if (Parser.getTok().is(AsmToken::RBrac)) {
2851 // "Dn[]" is the 'all lanes' syntax.
2852 LaneKind = AllLanes;
2853 Parser.Lex(); // Eat the ']'.
2854 return MatchOperand_Success;
2855 }
Jim Grosbachc9313252011-12-21 01:19:23 +00002856 const MCExpr *LaneIndex;
2857 SMLoc Loc = Parser.getTok().getLoc();
2858 if (getParser().ParseExpression(LaneIndex)) {
2859 Error(Loc, "illegal expression");
2860 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002861 }
Jim Grosbachc9313252011-12-21 01:19:23 +00002862 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LaneIndex);
2863 if (!CE) {
2864 Error(Loc, "lane index must be empty or an integer");
2865 return MatchOperand_ParseFail;
2866 }
2867 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2868 Error(Parser.getTok().getLoc(), "']' expected");
2869 return MatchOperand_ParseFail;
2870 }
2871 Parser.Lex(); // Eat the ']'.
2872 int64_t Val = CE->getValue();
2873
2874 // FIXME: Make this range check context sensitive for .8, .16, .32.
2875 if (Val < 0 || Val > 7) {
2876 Error(Parser.getTok().getLoc(), "lane index out of range");
2877 return MatchOperand_ParseFail;
2878 }
2879 Index = Val;
2880 LaneKind = IndexedLane;
2881 return MatchOperand_Success;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002882 }
2883 LaneKind = NoLanes;
2884 return MatchOperand_Success;
2885}
2886
Jim Grosbach862019c2011-10-18 23:02:30 +00002887// parse a vector register list
2888ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2889parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002890 VectorLaneTy LaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002891 unsigned LaneIndex;
Jim Grosbach5c984e42011-11-15 21:45:55 +00002892 SMLoc S = Parser.getTok().getLoc();
2893 // As an extension (to match gas), support a plain D register or Q register
2894 // (without encosing curly braces) as a single or double entry list,
2895 // respectively.
2896 if (Parser.getTok().is(AsmToken::Identifier)) {
2897 int Reg = tryParseRegister();
2898 if (Reg == -1)
2899 return MatchOperand_NoMatch;
2900 SMLoc E = Parser.getTok().getLoc();
2901 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002902 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002903 if (Res != MatchOperand_Success)
2904 return Res;
2905 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002906 case NoLanes:
2907 E = Parser.getTok().getLoc();
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002908 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002909 break;
2910 case AllLanes:
2911 E = Parser.getTok().getLoc();
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002912 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false,
2913 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002914 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002915 case IndexedLane:
2916 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002917 LaneIndex,
2918 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00002919 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002920 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002921 return MatchOperand_Success;
2922 }
2923 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2924 Reg = getDRegFromQReg(Reg);
Jim Grosbach7636bf62011-12-02 00:35:16 +00002925 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002926 if (Res != MatchOperand_Success)
2927 return Res;
2928 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002929 case NoLanes:
2930 E = Parser.getTok().getLoc();
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002931 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002932 break;
2933 case AllLanes:
2934 E = Parser.getTok().getLoc();
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002935 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, false,
2936 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002937 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002938 case IndexedLane:
2939 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002940 LaneIndex,
2941 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00002942 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002943 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002944 return MatchOperand_Success;
2945 }
2946 Error(S, "vector register expected");
2947 return MatchOperand_ParseFail;
2948 }
2949
2950 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbach862019c2011-10-18 23:02:30 +00002951 return MatchOperand_NoMatch;
2952
Jim Grosbach862019c2011-10-18 23:02:30 +00002953 Parser.Lex(); // Eat '{' token.
2954 SMLoc RegLoc = Parser.getTok().getLoc();
2955
2956 int Reg = tryParseRegister();
2957 if (Reg == -1) {
2958 Error(RegLoc, "register expected");
2959 return MatchOperand_ParseFail;
2960 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002961 unsigned Count = 1;
Jim Grosbach276ed032011-12-15 21:54:55 +00002962 int Spacing = 0;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002963 unsigned FirstReg = Reg;
2964 // The list is of D registers, but we also allow Q regs and just interpret
2965 // them as the two D sub-registers.
2966 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2967 FirstReg = Reg = getDRegFromQReg(Reg);
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002968 Spacing = 1; // double-spacing requires explicit D registers, otherwise
2969 // it's ambiguous with four-register single spaced.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002970 ++Reg;
2971 ++Count;
2972 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00002973 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002974 return MatchOperand_ParseFail;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002975
Jim Grosbache43862b2011-11-15 23:19:15 +00002976 while (Parser.getTok().is(AsmToken::Comma) ||
2977 Parser.getTok().is(AsmToken::Minus)) {
2978 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002979 if (!Spacing)
2980 Spacing = 1; // Register range implies a single spaced list.
2981 else if (Spacing == 2) {
2982 Error(Parser.getTok().getLoc(),
2983 "sequential registers in double spaced list");
2984 return MatchOperand_ParseFail;
2985 }
Jim Grosbache43862b2011-11-15 23:19:15 +00002986 Parser.Lex(); // Eat the minus.
2987 SMLoc EndLoc = Parser.getTok().getLoc();
2988 int EndReg = tryParseRegister();
2989 if (EndReg == -1) {
2990 Error(EndLoc, "register expected");
2991 return MatchOperand_ParseFail;
2992 }
2993 // Allow Q regs and just interpret them as the two D sub-registers.
2994 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2995 EndReg = getDRegFromQReg(EndReg) + 1;
2996 // If the register is the same as the start reg, there's nothing
2997 // more to do.
2998 if (Reg == EndReg)
2999 continue;
3000 // The register must be in the same register class as the first.
3001 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
3002 Error(EndLoc, "invalid register in register list");
3003 return MatchOperand_ParseFail;
3004 }
3005 // Ranges must go from low to high.
3006 if (Reg > EndReg) {
3007 Error(EndLoc, "bad range in register list");
3008 return MatchOperand_ParseFail;
3009 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00003010 // Parse the lane specifier if present.
3011 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003012 unsigned NextLaneIndex;
3013 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003014 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003015 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003016 Error(EndLoc, "mismatched lane index in register list");
3017 return MatchOperand_ParseFail;
3018 }
3019 EndLoc = Parser.getTok().getLoc();
Jim Grosbache43862b2011-11-15 23:19:15 +00003020
3021 // Add all the registers in the range to the register list.
3022 Count += EndReg - Reg;
3023 Reg = EndReg;
3024 continue;
3025 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003026 Parser.Lex(); // Eat the comma.
3027 RegLoc = Parser.getTok().getLoc();
3028 int OldReg = Reg;
3029 Reg = tryParseRegister();
3030 if (Reg == -1) {
3031 Error(RegLoc, "register expected");
3032 return MatchOperand_ParseFail;
3033 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003034 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00003035 // It's OK to use the enumeration values directly here rather, as the
3036 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003037 //
3038 // The list is of D registers, but we also allow Q regs and just interpret
3039 // them as the two D sub-registers.
3040 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003041 if (!Spacing)
3042 Spacing = 1; // Register range implies a single spaced list.
3043 else if (Spacing == 2) {
3044 Error(RegLoc,
3045 "invalid register in double-spaced list (must be 'D' register')");
3046 return MatchOperand_ParseFail;
3047 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003048 Reg = getDRegFromQReg(Reg);
3049 if (Reg != OldReg + 1) {
3050 Error(RegLoc, "non-contiguous register range");
3051 return MatchOperand_ParseFail;
3052 }
3053 ++Reg;
3054 Count += 2;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003055 // Parse the lane specifier if present.
3056 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003057 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003058 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003059 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003060 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003061 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003062 Error(EndLoc, "mismatched lane index in register list");
3063 return MatchOperand_ParseFail;
3064 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003065 continue;
3066 }
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003067 // Normal D register.
3068 // Figure out the register spacing (single or double) of the list if
3069 // we don't know it already.
3070 if (!Spacing)
3071 Spacing = 1 + (Reg == OldReg + 2);
3072
3073 // Just check that it's contiguous and keep going.
3074 if (Reg != OldReg + Spacing) {
Jim Grosbach862019c2011-10-18 23:02:30 +00003075 Error(RegLoc, "non-contiguous register range");
3076 return MatchOperand_ParseFail;
3077 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003078 ++Count;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003079 // Parse the lane specifier if present.
3080 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003081 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003082 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003083 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003084 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003085 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003086 Error(EndLoc, "mismatched lane index in register list");
3087 return MatchOperand_ParseFail;
3088 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003089 }
3090
3091 SMLoc E = Parser.getTok().getLoc();
3092 if (Parser.getTok().isNot(AsmToken::RCurly)) {
3093 Error(E, "'}' expected");
3094 return MatchOperand_ParseFail;
3095 }
3096 Parser.Lex(); // Eat '}' token.
3097
Jim Grosbach98b05a52011-11-30 01:09:44 +00003098 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003099 case NoLanes:
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003100 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count,
3101 (Spacing == 2), S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003102 break;
3103 case AllLanes:
3104 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00003105 (Spacing == 2),
Jim Grosbach98b05a52011-11-30 01:09:44 +00003106 S, E));
3107 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003108 case IndexedLane:
3109 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00003110 LaneIndex,
3111 (Spacing == 2),
3112 S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00003113 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003114 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003115 return MatchOperand_Success;
3116}
3117
Jim Grosbach43904292011-07-25 20:14:50 +00003118/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00003119ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003120parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003121 SMLoc S = Parser.getTok().getLoc();
3122 const AsmToken &Tok = Parser.getTok();
3123 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3124 StringRef OptStr = Tok.getString();
3125
3126 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
3127 .Case("sy", ARM_MB::SY)
3128 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003129 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003130 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003131 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003132 .Case("ishst", ARM_MB::ISHST)
3133 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003134 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003135 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003136 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003137 .Case("osh", ARM_MB::OSH)
3138 .Case("oshst", ARM_MB::OSHST)
3139 .Default(~0U);
3140
3141 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00003142 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003143
3144 Parser.Lex(); // Eat identifier token.
3145 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00003146 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003147}
3148
Jim Grosbach43904292011-07-25 20:14:50 +00003149/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003150ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003151parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003152 SMLoc S = Parser.getTok().getLoc();
3153 const AsmToken &Tok = Parser.getTok();
3154 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3155 StringRef IFlagsStr = Tok.getString();
3156
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003157 // An iflags string of "none" is interpreted to mean that none of the AIF
3158 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003159 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003160 if (IFlagsStr != "none") {
3161 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
3162 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
3163 .Case("a", ARM_PROC::A)
3164 .Case("i", ARM_PROC::I)
3165 .Case("f", ARM_PROC::F)
3166 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003167
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003168 // If some specific iflag is already set, it means that some letter is
3169 // present more than once, this is not acceptable.
3170 if (Flag == ~0U || (IFlags & Flag))
3171 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003172
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003173 IFlags |= Flag;
3174 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003175 }
3176
3177 Parser.Lex(); // Eat identifier token.
3178 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
3179 return MatchOperand_Success;
3180}
3181
Jim Grosbach43904292011-07-25 20:14:50 +00003182/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003183ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003184parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003185 SMLoc S = Parser.getTok().getLoc();
3186 const AsmToken &Tok = Parser.getTok();
3187 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3188 StringRef Mask = Tok.getString();
3189
James Molloyacad68d2011-09-28 14:21:38 +00003190 if (isMClass()) {
3191 // See ARMv6-M 10.1.1
3192 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
3193 .Case("apsr", 0)
3194 .Case("iapsr", 1)
3195 .Case("eapsr", 2)
3196 .Case("xpsr", 3)
3197 .Case("ipsr", 5)
3198 .Case("epsr", 6)
3199 .Case("iepsr", 7)
3200 .Case("msp", 8)
3201 .Case("psp", 9)
3202 .Case("primask", 16)
3203 .Case("basepri", 17)
3204 .Case("basepri_max", 18)
3205 .Case("faultmask", 19)
3206 .Case("control", 20)
3207 .Default(~0U);
Jim Grosbach18c8d122011-12-22 17:17:10 +00003208
James Molloyacad68d2011-09-28 14:21:38 +00003209 if (FlagsVal == ~0U)
3210 return MatchOperand_NoMatch;
3211
3212 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
3213 // basepri, basepri_max and faultmask only valid for V7m.
3214 return MatchOperand_NoMatch;
Jim Grosbach18c8d122011-12-22 17:17:10 +00003215
James Molloyacad68d2011-09-28 14:21:38 +00003216 Parser.Lex(); // Eat identifier token.
3217 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3218 return MatchOperand_Success;
3219 }
3220
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003221 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
3222 size_t Start = 0, Next = Mask.find('_');
3223 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00003224 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003225 if (Next != StringRef::npos)
3226 Flags = Mask.slice(Next+1, Mask.size());
3227
3228 // FlagsVal contains the complete mask:
3229 // 3-0: Mask
3230 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3231 unsigned FlagsVal = 0;
3232
3233 if (SpecReg == "apsr") {
3234 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00003235 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003236 .Case("g", 0x4) // same as CPSR_s
3237 .Case("nzcvqg", 0xc) // same as CPSR_fs
3238 .Default(~0U);
3239
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003240 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003241 if (!Flags.empty())
3242 return MatchOperand_NoMatch;
3243 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00003244 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003245 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003246 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00003247 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
3248 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003249 for (int i = 0, e = Flags.size(); i != e; ++i) {
3250 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
3251 .Case("c", 1)
3252 .Case("x", 2)
3253 .Case("s", 4)
3254 .Case("f", 8)
3255 .Default(~0U);
3256
3257 // If some specific flag is already set, it means that some letter is
3258 // present more than once, this is not acceptable.
3259 if (FlagsVal == ~0U || (FlagsVal & Flag))
3260 return MatchOperand_NoMatch;
3261 FlagsVal |= Flag;
3262 }
3263 } else // No match for special register.
3264 return MatchOperand_NoMatch;
3265
Owen Anderson7784f1d2011-10-21 18:43:28 +00003266 // Special register without flags is NOT equivalent to "fc" flags.
3267 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3268 // two lines would enable gas compatibility at the expense of breaking
3269 // round-tripping.
3270 //
3271 // if (!FlagsVal)
3272 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003273
3274 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3275 if (SpecReg == "spsr")
3276 FlagsVal |= 16;
3277
3278 Parser.Lex(); // Eat identifier token.
3279 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3280 return MatchOperand_Success;
3281}
3282
Jim Grosbachf6c05252011-07-21 17:23:04 +00003283ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3284parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3285 int Low, int High) {
3286 const AsmToken &Tok = Parser.getTok();
3287 if (Tok.isNot(AsmToken::Identifier)) {
3288 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3289 return MatchOperand_ParseFail;
3290 }
3291 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00003292 std::string LowerOp = Op.lower();
3293 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00003294 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3295 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3296 return MatchOperand_ParseFail;
3297 }
3298 Parser.Lex(); // Eat shift type token.
3299
3300 // There must be a '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003301 if (Parser.getTok().isNot(AsmToken::Hash) &&
3302 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbachf6c05252011-07-21 17:23:04 +00003303 Error(Parser.getTok().getLoc(), "'#' expected");
3304 return MatchOperand_ParseFail;
3305 }
3306 Parser.Lex(); // Eat hash token.
3307
3308 const MCExpr *ShiftAmount;
3309 SMLoc Loc = Parser.getTok().getLoc();
3310 if (getParser().ParseExpression(ShiftAmount)) {
3311 Error(Loc, "illegal expression");
3312 return MatchOperand_ParseFail;
3313 }
3314 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3315 if (!CE) {
3316 Error(Loc, "constant expression expected");
3317 return MatchOperand_ParseFail;
3318 }
3319 int Val = CE->getValue();
3320 if (Val < Low || Val > High) {
3321 Error(Loc, "immediate value out of range");
3322 return MatchOperand_ParseFail;
3323 }
3324
3325 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3326
3327 return MatchOperand_Success;
3328}
3329
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003330ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3331parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3332 const AsmToken &Tok = Parser.getTok();
3333 SMLoc S = Tok.getLoc();
3334 if (Tok.isNot(AsmToken::Identifier)) {
3335 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3336 return MatchOperand_ParseFail;
3337 }
3338 int Val = StringSwitch<int>(Tok.getString())
3339 .Case("be", 1)
3340 .Case("le", 0)
3341 .Default(-1);
3342 Parser.Lex(); // Eat the token.
3343
3344 if (Val == -1) {
3345 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3346 return MatchOperand_ParseFail;
3347 }
3348 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3349 getContext()),
3350 S, Parser.getTok().getLoc()));
3351 return MatchOperand_Success;
3352}
3353
Jim Grosbach580f4a92011-07-25 22:20:28 +00003354/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3355/// instructions. Legal values are:
3356/// lsl #n 'n' in [0,31]
3357/// asr #n 'n' in [1,32]
3358/// n == 32 encoded as n == 0.
3359ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3360parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3361 const AsmToken &Tok = Parser.getTok();
3362 SMLoc S = Tok.getLoc();
3363 if (Tok.isNot(AsmToken::Identifier)) {
3364 Error(S, "shift operator 'asr' or 'lsl' expected");
3365 return MatchOperand_ParseFail;
3366 }
3367 StringRef ShiftName = Tok.getString();
3368 bool isASR;
3369 if (ShiftName == "lsl" || ShiftName == "LSL")
3370 isASR = false;
3371 else if (ShiftName == "asr" || ShiftName == "ASR")
3372 isASR = true;
3373 else {
3374 Error(S, "shift operator 'asr' or 'lsl' expected");
3375 return MatchOperand_ParseFail;
3376 }
3377 Parser.Lex(); // Eat the operator.
3378
3379 // A '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003380 if (Parser.getTok().isNot(AsmToken::Hash) &&
3381 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach580f4a92011-07-25 22:20:28 +00003382 Error(Parser.getTok().getLoc(), "'#' expected");
3383 return MatchOperand_ParseFail;
3384 }
3385 Parser.Lex(); // Eat hash token.
3386
3387 const MCExpr *ShiftAmount;
3388 SMLoc E = Parser.getTok().getLoc();
3389 if (getParser().ParseExpression(ShiftAmount)) {
3390 Error(E, "malformed shift expression");
3391 return MatchOperand_ParseFail;
3392 }
3393 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3394 if (!CE) {
3395 Error(E, "shift amount must be an immediate");
3396 return MatchOperand_ParseFail;
3397 }
3398
3399 int64_t Val = CE->getValue();
3400 if (isASR) {
3401 // Shift amount must be in [1,32]
3402 if (Val < 1 || Val > 32) {
3403 Error(E, "'asr' shift amount must be in range [1,32]");
3404 return MatchOperand_ParseFail;
3405 }
Owen Anderson0afa0092011-09-26 21:06:22 +00003406 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3407 if (isThumb() && Val == 32) {
3408 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3409 return MatchOperand_ParseFail;
3410 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00003411 if (Val == 32) Val = 0;
3412 } else {
3413 // Shift amount must be in [1,32]
3414 if (Val < 0 || Val > 31) {
3415 Error(E, "'lsr' shift amount must be in range [0,31]");
3416 return MatchOperand_ParseFail;
3417 }
3418 }
3419
3420 E = Parser.getTok().getLoc();
3421 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3422
3423 return MatchOperand_Success;
3424}
3425
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003426/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3427/// of instructions. Legal values are:
3428/// ror #n 'n' in {0, 8, 16, 24}
3429ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3430parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3431 const AsmToken &Tok = Parser.getTok();
3432 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00003433 if (Tok.isNot(AsmToken::Identifier))
3434 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003435 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00003436 if (ShiftName != "ror" && ShiftName != "ROR")
3437 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003438 Parser.Lex(); // Eat the operator.
3439
3440 // A '#' and a rotate amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003441 if (Parser.getTok().isNot(AsmToken::Hash) &&
3442 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003443 Error(Parser.getTok().getLoc(), "'#' expected");
3444 return MatchOperand_ParseFail;
3445 }
3446 Parser.Lex(); // Eat hash token.
3447
3448 const MCExpr *ShiftAmount;
3449 SMLoc E = Parser.getTok().getLoc();
3450 if (getParser().ParseExpression(ShiftAmount)) {
3451 Error(E, "malformed rotate expression");
3452 return MatchOperand_ParseFail;
3453 }
3454 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3455 if (!CE) {
3456 Error(E, "rotate amount must be an immediate");
3457 return MatchOperand_ParseFail;
3458 }
3459
3460 int64_t Val = CE->getValue();
3461 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3462 // normally, zero is represented in asm by omitting the rotate operand
3463 // entirely.
3464 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3465 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3466 return MatchOperand_ParseFail;
3467 }
3468
3469 E = Parser.getTok().getLoc();
3470 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3471
3472 return MatchOperand_Success;
3473}
3474
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003475ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3476parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3477 SMLoc S = Parser.getTok().getLoc();
3478 // The bitfield descriptor is really two operands, the LSB and the width.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003479 if (Parser.getTok().isNot(AsmToken::Hash) &&
3480 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003481 Error(Parser.getTok().getLoc(), "'#' expected");
3482 return MatchOperand_ParseFail;
3483 }
3484 Parser.Lex(); // Eat hash token.
3485
3486 const MCExpr *LSBExpr;
3487 SMLoc E = Parser.getTok().getLoc();
3488 if (getParser().ParseExpression(LSBExpr)) {
3489 Error(E, "malformed immediate expression");
3490 return MatchOperand_ParseFail;
3491 }
3492 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3493 if (!CE) {
3494 Error(E, "'lsb' operand must be an immediate");
3495 return MatchOperand_ParseFail;
3496 }
3497
3498 int64_t LSB = CE->getValue();
3499 // The LSB must be in the range [0,31]
3500 if (LSB < 0 || LSB > 31) {
3501 Error(E, "'lsb' operand must be in the range [0,31]");
3502 return MatchOperand_ParseFail;
3503 }
3504 E = Parser.getTok().getLoc();
3505
3506 // Expect another immediate operand.
3507 if (Parser.getTok().isNot(AsmToken::Comma)) {
3508 Error(Parser.getTok().getLoc(), "too few operands");
3509 return MatchOperand_ParseFail;
3510 }
3511 Parser.Lex(); // Eat hash token.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003512 if (Parser.getTok().isNot(AsmToken::Hash) &&
3513 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003514 Error(Parser.getTok().getLoc(), "'#' expected");
3515 return MatchOperand_ParseFail;
3516 }
3517 Parser.Lex(); // Eat hash token.
3518
3519 const MCExpr *WidthExpr;
3520 if (getParser().ParseExpression(WidthExpr)) {
3521 Error(E, "malformed immediate expression");
3522 return MatchOperand_ParseFail;
3523 }
3524 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3525 if (!CE) {
3526 Error(E, "'width' operand must be an immediate");
3527 return MatchOperand_ParseFail;
3528 }
3529
3530 int64_t Width = CE->getValue();
3531 // The LSB must be in the range [1,32-lsb]
3532 if (Width < 1 || Width > 32 - LSB) {
3533 Error(E, "'width' operand must be in the range [1,32-lsb]");
3534 return MatchOperand_ParseFail;
3535 }
3536 E = Parser.getTok().getLoc();
3537
3538 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3539
3540 return MatchOperand_Success;
3541}
3542
Jim Grosbach7ce05792011-08-03 23:50:40 +00003543ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3544parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3545 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003546 // postidx_reg := '+' register {, shift}
3547 // | '-' register {, shift}
3548 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003549
3550 // This method must return MatchOperand_NoMatch without consuming any tokens
3551 // in the case where there is no match, as other alternatives take other
3552 // parse methods.
3553 AsmToken Tok = Parser.getTok();
3554 SMLoc S = Tok.getLoc();
3555 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003556 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003557 int Reg = -1;
3558 if (Tok.is(AsmToken::Plus)) {
3559 Parser.Lex(); // Eat the '+' token.
3560 haveEaten = true;
3561 } else if (Tok.is(AsmToken::Minus)) {
3562 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003563 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003564 haveEaten = true;
3565 }
3566 if (Parser.getTok().is(AsmToken::Identifier))
3567 Reg = tryParseRegister();
3568 if (Reg == -1) {
3569 if (!haveEaten)
3570 return MatchOperand_NoMatch;
3571 Error(Parser.getTok().getLoc(), "register expected");
3572 return MatchOperand_ParseFail;
3573 }
3574 SMLoc E = Parser.getTok().getLoc();
3575
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003576 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3577 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003578 if (Parser.getTok().is(AsmToken::Comma)) {
3579 Parser.Lex(); // Eat the ','.
3580 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3581 return MatchOperand_ParseFail;
3582 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003583
3584 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3585 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003586
3587 return MatchOperand_Success;
3588}
3589
Jim Grosbach251bf252011-08-10 21:56:18 +00003590ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3591parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3592 // Check for a post-index addressing register operand. Specifically:
3593 // am3offset := '+' register
3594 // | '-' register
3595 // | register
3596 // | # imm
3597 // | # + imm
3598 // | # - imm
3599
3600 // This method must return MatchOperand_NoMatch without consuming any tokens
3601 // in the case where there is no match, as other alternatives take other
3602 // parse methods.
3603 AsmToken Tok = Parser.getTok();
3604 SMLoc S = Tok.getLoc();
3605
3606 // Do immediates first, as we always parse those if we have a '#'.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003607 if (Parser.getTok().is(AsmToken::Hash) ||
3608 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach251bf252011-08-10 21:56:18 +00003609 Parser.Lex(); // Eat the '#'.
3610 // Explicitly look for a '-', as we need to encode negative zero
3611 // differently.
3612 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3613 const MCExpr *Offset;
3614 if (getParser().ParseExpression(Offset))
3615 return MatchOperand_ParseFail;
3616 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3617 if (!CE) {
3618 Error(S, "constant expression expected");
3619 return MatchOperand_ParseFail;
3620 }
3621 SMLoc E = Tok.getLoc();
3622 // Negative zero is encoded as the flag value INT32_MIN.
3623 int32_t Val = CE->getValue();
3624 if (isNegative && Val == 0)
3625 Val = INT32_MIN;
3626
3627 Operands.push_back(
3628 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3629
3630 return MatchOperand_Success;
3631 }
3632
3633
3634 bool haveEaten = false;
3635 bool isAdd = true;
3636 int Reg = -1;
3637 if (Tok.is(AsmToken::Plus)) {
3638 Parser.Lex(); // Eat the '+' token.
3639 haveEaten = true;
3640 } else if (Tok.is(AsmToken::Minus)) {
3641 Parser.Lex(); // Eat the '-' token.
3642 isAdd = false;
3643 haveEaten = true;
3644 }
3645 if (Parser.getTok().is(AsmToken::Identifier))
3646 Reg = tryParseRegister();
3647 if (Reg == -1) {
3648 if (!haveEaten)
3649 return MatchOperand_NoMatch;
3650 Error(Parser.getTok().getLoc(), "register expected");
3651 return MatchOperand_ParseFail;
3652 }
3653 SMLoc E = Parser.getTok().getLoc();
3654
3655 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3656 0, S, E));
3657
3658 return MatchOperand_Success;
3659}
3660
Jim Grosbacha77295d2011-09-08 22:07:06 +00003661/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3662/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3663/// when they refer multiple MIOperands inside a single one.
3664bool ARMAsmParser::
3665cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3666 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3667 // Rt, Rt2
3668 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3669 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3670 // Create a writeback register dummy placeholder.
3671 Inst.addOperand(MCOperand::CreateReg(0));
3672 // addr
3673 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3674 // pred
3675 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3676 return true;
3677}
3678
3679/// cvtT2StrdPre - Convert parsed operands to MCInst.
3680/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3681/// when they refer multiple MIOperands inside a single one.
3682bool ARMAsmParser::
3683cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3684 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3685 // Create a writeback register dummy placeholder.
3686 Inst.addOperand(MCOperand::CreateReg(0));
3687 // Rt, Rt2
3688 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3689 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3690 // addr
3691 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3692 // pred
3693 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3694 return true;
3695}
3696
Jim Grosbacheeec0252011-09-08 00:39:19 +00003697/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3698/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3699/// when they refer multiple MIOperands inside a single one.
3700bool ARMAsmParser::
3701cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3702 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3703 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3704
3705 // Create a writeback register dummy placeholder.
3706 Inst.addOperand(MCOperand::CreateImm(0));
3707
3708 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3709 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3710 return true;
3711}
3712
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003713/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3714/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3715/// when they refer multiple MIOperands inside a single one.
3716bool ARMAsmParser::
3717cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3718 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3719 // Create a writeback register dummy placeholder.
3720 Inst.addOperand(MCOperand::CreateImm(0));
3721 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3722 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3723 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3724 return true;
3725}
3726
Jim Grosbach1355cf12011-07-26 17:10:22 +00003727/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003728/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3729/// when they refer multiple MIOperands inside a single one.
3730bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003731cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003732 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3733 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3734
3735 // Create a writeback register dummy placeholder.
3736 Inst.addOperand(MCOperand::CreateImm(0));
3737
Jim Grosbach7ce05792011-08-03 23:50:40 +00003738 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003739 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3740 return true;
3741}
3742
Owen Anderson9ab0f252011-08-26 20:43:14 +00003743/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3744/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3745/// when they refer multiple MIOperands inside a single one.
3746bool ARMAsmParser::
3747cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3748 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3749 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3750
3751 // Create a writeback register dummy placeholder.
3752 Inst.addOperand(MCOperand::CreateImm(0));
3753
3754 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3755 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3756 return true;
3757}
3758
3759
Jim Grosbach548340c2011-08-11 19:22:40 +00003760/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3761/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3762/// when they refer multiple MIOperands inside a single one.
3763bool ARMAsmParser::
3764cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3765 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3766 // Create a writeback register dummy placeholder.
3767 Inst.addOperand(MCOperand::CreateImm(0));
3768 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3769 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3770 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3771 return true;
3772}
3773
Jim Grosbach1355cf12011-07-26 17:10:22 +00003774/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003775/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3776/// when they refer multiple MIOperands inside a single one.
3777bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003778cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003779 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3780 // Create a writeback register dummy placeholder.
3781 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003782 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3783 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3784 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003785 return true;
3786}
3787
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003788/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3789/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3790/// when they refer multiple MIOperands inside a single one.
3791bool ARMAsmParser::
3792cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3793 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3794 // Create a writeback register dummy placeholder.
3795 Inst.addOperand(MCOperand::CreateImm(0));
3796 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3797 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3798 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3799 return true;
3800}
3801
Jim Grosbach7ce05792011-08-03 23:50:40 +00003802/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3803/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3804/// when they refer multiple MIOperands inside a single one.
3805bool ARMAsmParser::
3806cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3807 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3808 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003809 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003810 // Create a writeback register dummy placeholder.
3811 Inst.addOperand(MCOperand::CreateImm(0));
3812 // addr
3813 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3814 // offset
3815 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3816 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003817 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3818 return true;
3819}
3820
Jim Grosbach7ce05792011-08-03 23:50:40 +00003821/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003822/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3823/// when they refer multiple MIOperands inside a single one.
3824bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003825cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3826 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3827 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003828 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003829 // Create a writeback register dummy placeholder.
3830 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003831 // addr
3832 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3833 // offset
3834 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3835 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003836 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3837 return true;
3838}
3839
Jim Grosbach7ce05792011-08-03 23:50:40 +00003840/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003841/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3842/// when they refer multiple MIOperands inside a single one.
3843bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003844cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3845 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003846 // Create a writeback register dummy placeholder.
3847 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003848 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003849 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003850 // addr
3851 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3852 // offset
3853 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3854 // pred
3855 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3856 return true;
3857}
3858
3859/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3860/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3861/// when they refer multiple MIOperands inside a single one.
3862bool ARMAsmParser::
3863cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3864 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3865 // Create a writeback register dummy placeholder.
3866 Inst.addOperand(MCOperand::CreateImm(0));
3867 // Rt
3868 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3869 // addr
3870 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3871 // offset
3872 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3873 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003874 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3875 return true;
3876}
3877
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003878/// cvtLdrdPre - Convert parsed operands to MCInst.
3879/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3880/// when they refer multiple MIOperands inside a single one.
3881bool ARMAsmParser::
3882cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3883 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3884 // Rt, Rt2
3885 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3886 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3887 // Create a writeback register dummy placeholder.
3888 Inst.addOperand(MCOperand::CreateImm(0));
3889 // addr
3890 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3891 // pred
3892 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3893 return true;
3894}
3895
Jim Grosbach14605d12011-08-11 20:28:23 +00003896/// cvtStrdPre - Convert parsed operands to MCInst.
3897/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3898/// when they refer multiple MIOperands inside a single one.
3899bool ARMAsmParser::
3900cvtStrdPre(MCInst &Inst, unsigned Opcode,
3901 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3902 // Create a writeback register dummy placeholder.
3903 Inst.addOperand(MCOperand::CreateImm(0));
3904 // Rt, Rt2
3905 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3906 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3907 // addr
3908 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3909 // pred
3910 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3911 return true;
3912}
3913
Jim Grosbach623a4542011-08-10 22:42:16 +00003914/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3915/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3916/// when they refer multiple MIOperands inside a single one.
3917bool ARMAsmParser::
3918cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3919 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3920 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3921 // Create a writeback register dummy placeholder.
3922 Inst.addOperand(MCOperand::CreateImm(0));
3923 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3924 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3925 return true;
3926}
3927
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003928/// cvtThumbMultiple- Convert parsed operands to MCInst.
3929/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3930/// when they refer multiple MIOperands inside a single one.
3931bool ARMAsmParser::
3932cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3933 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3934 // The second source operand must be the same register as the destination
3935 // operand.
3936 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003937 (((ARMOperand*)Operands[3])->getReg() !=
3938 ((ARMOperand*)Operands[5])->getReg()) &&
3939 (((ARMOperand*)Operands[3])->getReg() !=
3940 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003941 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003942 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003943 return false;
3944 }
3945 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3946 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach1b332862011-11-10 22:10:12 +00003947 // If we have a three-operand form, make sure to set Rn to be the operand
3948 // that isn't the same as Rd.
3949 unsigned RegOp = 4;
3950 if (Operands.size() == 6 &&
3951 ((ARMOperand*)Operands[4])->getReg() ==
3952 ((ARMOperand*)Operands[3])->getReg())
3953 RegOp = 5;
3954 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
3955 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003956 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3957
3958 return true;
3959}
Jim Grosbach623a4542011-08-10 22:42:16 +00003960
Jim Grosbach12431322011-10-24 22:16:58 +00003961bool ARMAsmParser::
3962cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3963 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3964 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003965 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003966 // Create a writeback register dummy placeholder.
3967 Inst.addOperand(MCOperand::CreateImm(0));
3968 // Vn
3969 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3970 // pred
3971 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3972 return true;
3973}
3974
3975bool ARMAsmParser::
3976cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3977 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3978 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003979 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003980 // Create a writeback register dummy placeholder.
3981 Inst.addOperand(MCOperand::CreateImm(0));
3982 // Vn
3983 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3984 // Vm
3985 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3986 // pred
3987 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3988 return true;
3989}
3990
Jim Grosbach4334e032011-10-31 21:50:31 +00003991bool ARMAsmParser::
3992cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
3993 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3994 // Create a writeback register dummy placeholder.
3995 Inst.addOperand(MCOperand::CreateImm(0));
3996 // Vn
3997 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3998 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003999 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00004000 // pred
4001 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4002 return true;
4003}
4004
4005bool ARMAsmParser::
4006cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
4007 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4008 // Create a writeback register dummy placeholder.
4009 Inst.addOperand(MCOperand::CreateImm(0));
4010 // Vn
4011 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4012 // Vm
4013 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4014 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004015 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00004016 // pred
4017 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4018 return true;
4019}
4020
Bill Wendlinge7176102010-11-06 22:36:58 +00004021/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004022/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00004023bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00004024parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00004025 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00004026 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00004027 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00004028 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004029 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004030
Sean Callanan18b83232010-01-19 21:44:56 +00004031 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00004032 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00004033 if (BaseRegNum == -1)
4034 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004035
Daniel Dunbar05710932011-01-18 05:34:17 +00004036 // The next token must either be a comma or a closing bracket.
4037 const AsmToken &Tok = Parser.getTok();
4038 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004039 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00004040
Jim Grosbach7ce05792011-08-03 23:50:40 +00004041 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00004042 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004043 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004044
Jim Grosbach7ce05792011-08-03 23:50:40 +00004045 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004046 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00004047
Jim Grosbachfb12f352011-09-19 18:42:21 +00004048 // If there's a pre-indexing writeback marker, '!', just add it as a token
4049 // operand. It's rather odd, but syntactically valid.
4050 if (Parser.getTok().is(AsmToken::Exclaim)) {
4051 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4052 Parser.Lex(); // Eat the '!'.
4053 }
4054
Jim Grosbach7ce05792011-08-03 23:50:40 +00004055 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004056 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004057
Jim Grosbach7ce05792011-08-03 23:50:40 +00004058 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
4059 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004060
Jim Grosbach57dcb852011-10-11 17:29:55 +00004061 // If we have a ':', it's an alignment specifier.
4062 if (Parser.getTok().is(AsmToken::Colon)) {
4063 Parser.Lex(); // Eat the ':'.
4064 E = Parser.getTok().getLoc();
4065
4066 const MCExpr *Expr;
4067 if (getParser().ParseExpression(Expr))
4068 return true;
4069
4070 // The expression has to be a constant. Memory references with relocations
4071 // don't come through here, as they use the <label> forms of the relevant
4072 // instructions.
4073 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4074 if (!CE)
4075 return Error (E, "constant expression expected");
4076
4077 unsigned Align = 0;
4078 switch (CE->getValue()) {
4079 default:
Jim Grosbacheeaf1c12011-12-19 18:31:43 +00004080 return Error(E,
4081 "alignment specifier must be 16, 32, 64, 128, or 256 bits");
4082 case 16: Align = 2; break;
4083 case 32: Align = 4; break;
Jim Grosbach57dcb852011-10-11 17:29:55 +00004084 case 64: Align = 8; break;
4085 case 128: Align = 16; break;
4086 case 256: Align = 32; break;
4087 }
4088
4089 // Now we should have the closing ']'
4090 E = Parser.getTok().getLoc();
4091 if (Parser.getTok().isNot(AsmToken::RBrac))
4092 return Error(E, "']' expected");
4093 Parser.Lex(); // Eat right bracket token.
4094
4095 // Don't worry about range checking the value here. That's handled by
4096 // the is*() predicates.
4097 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
4098 ARM_AM::no_shift, 0, Align,
4099 false, S, E));
4100
4101 // If there's a pre-indexing writeback marker, '!', just add it as a token
4102 // operand.
4103 if (Parser.getTok().is(AsmToken::Exclaim)) {
4104 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4105 Parser.Lex(); // Eat the '!'.
4106 }
4107
4108 return false;
4109 }
4110
4111 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004112 // offset. Be friendly and also accept a plain integer (without a leading
4113 // hash) for gas compatibility.
4114 if (Parser.getTok().is(AsmToken::Hash) ||
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004115 Parser.getTok().is(AsmToken::Dollar) ||
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004116 Parser.getTok().is(AsmToken::Integer)) {
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004117 if (Parser.getTok().isNot(AsmToken::Integer))
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004118 Parser.Lex(); // Eat the '#'.
Jim Grosbach7ce05792011-08-03 23:50:40 +00004119 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004120
Owen Anderson0da10cf2011-08-29 19:36:44 +00004121 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00004122 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004123 if (getParser().ParseExpression(Offset))
4124 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004125
4126 // The expression has to be a constant. Memory references with relocations
4127 // don't come through here, as they use the <label> forms of the relevant
4128 // instructions.
4129 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
4130 if (!CE)
4131 return Error (E, "constant expression expected");
4132
Owen Anderson0da10cf2011-08-29 19:36:44 +00004133 // If the constant was #-0, represent it as INT32_MIN.
4134 int32_t Val = CE->getValue();
4135 if (isNegative && Val == 0)
4136 CE = MCConstantExpr::Create(INT32_MIN, getContext());
4137
Jim Grosbach7ce05792011-08-03 23:50:40 +00004138 // Now we should have the closing ']'
4139 E = Parser.getTok().getLoc();
4140 if (Parser.getTok().isNot(AsmToken::RBrac))
4141 return Error(E, "']' expected");
4142 Parser.Lex(); // Eat right bracket token.
4143
4144 // Don't worry about range checking the value here. That's handled by
4145 // the is*() predicates.
4146 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004147 ARM_AM::no_shift, 0, 0,
4148 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00004149
4150 // If there's a pre-indexing writeback marker, '!', just add it as a token
4151 // operand.
4152 if (Parser.getTok().is(AsmToken::Exclaim)) {
4153 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4154 Parser.Lex(); // Eat the '!'.
4155 }
4156
4157 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004158 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004159
4160 // The register offset is optionally preceded by a '+' or '-'
4161 bool isNegative = false;
4162 if (Parser.getTok().is(AsmToken::Minus)) {
4163 isNegative = true;
4164 Parser.Lex(); // Eat the '-'.
4165 } else if (Parser.getTok().is(AsmToken::Plus)) {
4166 // Nothing to do.
4167 Parser.Lex(); // Eat the '+'.
4168 }
4169
4170 E = Parser.getTok().getLoc();
4171 int OffsetRegNum = tryParseRegister();
4172 if (OffsetRegNum == -1)
4173 return Error(E, "register expected");
4174
4175 // If there's a shift operator, handle it.
4176 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004177 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004178 if (Parser.getTok().is(AsmToken::Comma)) {
4179 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004180 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004181 return true;
4182 }
4183
4184 // Now we should have the closing ']'
4185 E = Parser.getTok().getLoc();
4186 if (Parser.getTok().isNot(AsmToken::RBrac))
4187 return Error(E, "']' expected");
4188 Parser.Lex(); // Eat right bracket token.
4189
4190 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004191 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00004192 S, E));
4193
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00004194 // If there's a pre-indexing writeback marker, '!', just add it as a token
4195 // operand.
4196 if (Parser.getTok().is(AsmToken::Exclaim)) {
4197 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4198 Parser.Lex(); // Eat the '!'.
4199 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004200
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004201 return false;
4202}
4203
Jim Grosbach7ce05792011-08-03 23:50:40 +00004204/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004205/// ( lsl | lsr | asr | ror ) , # shift_amount
4206/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00004207/// return true if it parses a shift otherwise it returns false.
4208bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
4209 unsigned &Amount) {
4210 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00004211 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004212 if (Tok.isNot(AsmToken::Identifier))
4213 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00004214 StringRef ShiftName = Tok.getString();
Jim Grosbachaf4edea2011-12-07 23:40:58 +00004215 if (ShiftName == "lsl" || ShiftName == "LSL" ||
4216 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson00828302011-03-18 22:50:18 +00004217 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004218 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00004219 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004220 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00004221 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004222 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00004223 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004224 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00004225 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004226 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00004227 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00004228 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004229
Jim Grosbach7ce05792011-08-03 23:50:40 +00004230 // rrx stands alone.
4231 Amount = 0;
4232 if (St != ARM_AM::rrx) {
4233 Loc = Parser.getTok().getLoc();
4234 // A '#' and a shift amount.
4235 const AsmToken &HashTok = Parser.getTok();
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004236 if (HashTok.isNot(AsmToken::Hash) &&
4237 HashTok.isNot(AsmToken::Dollar))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004238 return Error(HashTok.getLoc(), "'#' expected");
4239 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004240
Jim Grosbach7ce05792011-08-03 23:50:40 +00004241 const MCExpr *Expr;
4242 if (getParser().ParseExpression(Expr))
4243 return true;
4244 // Range check the immediate.
4245 // lsl, ror: 0 <= imm <= 31
4246 // lsr, asr: 0 <= imm <= 32
4247 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4248 if (!CE)
4249 return Error(Loc, "shift amount must be an immediate");
4250 int64_t Imm = CE->getValue();
4251 if (Imm < 0 ||
4252 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4253 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4254 return Error(Loc, "immediate shift value out of range");
4255 Amount = Imm;
4256 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004257
4258 return false;
4259}
4260
Jim Grosbach9d390362011-10-03 23:38:36 +00004261/// parseFPImm - A floating point immediate expression operand.
4262ARMAsmParser::OperandMatchResultTy ARMAsmParser::
4263parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach51222d12012-01-20 18:09:51 +00004264 // Anything that can accept a floating point constant as an operand
4265 // needs to go through here, as the regular ParseExpression is
4266 // integer only.
4267 //
4268 // This routine still creates a generic Immediate operand, containing
4269 // a bitcast of the 64-bit floating point value. The various operands
4270 // that accept floats can check whether the value is valid for them
4271 // via the standard is*() predicates.
4272
Jim Grosbach9d390362011-10-03 23:38:36 +00004273 SMLoc S = Parser.getTok().getLoc();
4274
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004275 if (Parser.getTok().isNot(AsmToken::Hash) &&
4276 Parser.getTok().isNot(AsmToken::Dollar))
Jim Grosbach9d390362011-10-03 23:38:36 +00004277 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00004278
4279 // Disambiguate the VMOV forms that can accept an FP immediate.
4280 // vmov.f32 <sreg>, #imm
4281 // vmov.f64 <dreg>, #imm
4282 // vmov.f32 <dreg>, #imm @ vector f32x2
4283 // vmov.f32 <qreg>, #imm @ vector f32x4
4284 //
4285 // There are also the NEON VMOV instructions which expect an
4286 // integer constant. Make sure we don't try to parse an FPImm
4287 // for these:
4288 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4289 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4290 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4291 TyOp->getToken() != ".f64"))
4292 return MatchOperand_NoMatch;
4293
Jim Grosbach9d390362011-10-03 23:38:36 +00004294 Parser.Lex(); // Eat the '#'.
4295
4296 // Handle negation, as that still comes through as a separate token.
4297 bool isNegative = false;
4298 if (Parser.getTok().is(AsmToken::Minus)) {
4299 isNegative = true;
4300 Parser.Lex();
4301 }
4302 const AsmToken &Tok = Parser.getTok();
Jim Grosbachae69f702012-01-19 02:47:30 +00004303 SMLoc Loc = Tok.getLoc();
Jim Grosbach9d390362011-10-03 23:38:36 +00004304 if (Tok.is(AsmToken::Real)) {
Jim Grosbach51222d12012-01-20 18:09:51 +00004305 APFloat RealVal(APFloat::IEEEsingle, Tok.getString());
Jim Grosbach9d390362011-10-03 23:38:36 +00004306 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4307 // If we had a '-' in front, toggle the sign bit.
Jim Grosbach51222d12012-01-20 18:09:51 +00004308 IntVal ^= (uint64_t)isNegative << 31;
Jim Grosbach9d390362011-10-03 23:38:36 +00004309 Parser.Lex(); // Eat the token.
Jim Grosbach51222d12012-01-20 18:09:51 +00004310 Operands.push_back(ARMOperand::CreateImm(
4311 MCConstantExpr::Create(IntVal, getContext()),
4312 S, Parser.getTok().getLoc()));
Jim Grosbach9d390362011-10-03 23:38:36 +00004313 return MatchOperand_Success;
4314 }
Jim Grosbach51222d12012-01-20 18:09:51 +00004315 // Also handle plain integers. Instructions which allow floating point
4316 // immediates also allow a raw encoded 8-bit value.
Jim Grosbach9d390362011-10-03 23:38:36 +00004317 if (Tok.is(AsmToken::Integer)) {
4318 int64_t Val = Tok.getIntVal();
4319 Parser.Lex(); // Eat the token.
4320 if (Val > 255 || Val < 0) {
Jim Grosbachae69f702012-01-19 02:47:30 +00004321 Error(Loc, "encoded floating point value out of range");
Jim Grosbach9d390362011-10-03 23:38:36 +00004322 return MatchOperand_ParseFail;
4323 }
Jim Grosbach51222d12012-01-20 18:09:51 +00004324 double RealVal = ARM_AM::getFPImmFloat(Val);
4325 Val = APFloat(APFloat::IEEEdouble, RealVal).bitcastToAPInt().getZExtValue();
4326 Operands.push_back(ARMOperand::CreateImm(
4327 MCConstantExpr::Create(Val, getContext()), S,
4328 Parser.getTok().getLoc()));
Jim Grosbach9d390362011-10-03 23:38:36 +00004329 return MatchOperand_Success;
4330 }
4331
Jim Grosbachae69f702012-01-19 02:47:30 +00004332 Error(Loc, "invalid floating point immediate");
Jim Grosbach9d390362011-10-03 23:38:36 +00004333 return MatchOperand_ParseFail;
4334}
Jim Grosbach51222d12012-01-20 18:09:51 +00004335
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004336/// Parse a arm instruction operand. For now this parses the operand regardless
4337/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004338bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004339 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00004340 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004341
4342 // Check if the current operand has a custom associated parser, if so, try to
4343 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00004344 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4345 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004346 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00004347 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4348 // there was a match, but an error occurred, in which case, just return that
4349 // the operand parsing failed.
4350 if (ResTy == MatchOperand_ParseFail)
4351 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004352
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004353 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00004354 default:
4355 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00004356 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00004357 case AsmToken::Identifier: {
Jim Grosbach1355cf12011-07-26 17:10:22 +00004358 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00004359 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00004360 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00004361 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00004362 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00004363 else if (Res == -1) // irrecoverable error
4364 return true;
Jim Grosbach3cbe43f2011-12-20 22:26:38 +00004365 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004366 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
4367 S = Parser.getTok().getLoc();
4368 Parser.Lex();
4369 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
4370 return false;
4371 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00004372
4373 // Fall though for the Identifier case that is not a register or a
4374 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00004375 }
Jim Grosbach758a5192011-10-26 21:14:08 +00004376 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00004377 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00004378 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00004379 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00004380 // This was not a register so parse other operands that start with an
4381 // identifier (like labels) as expressions and create them as immediates.
4382 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00004383 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00004384 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004385 return true;
Sean Callanan76264762010-04-02 22:27:05 +00004386 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004387 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4388 return false;
4389 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004390 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004391 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00004392 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004393 return parseRegisterList(Operands);
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004394 case AsmToken::Dollar:
Owen Anderson63553c72011-08-29 17:17:09 +00004395 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00004396 // #42 -> immediate.
4397 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00004398 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004399 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00004400 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00004401 const MCExpr *ImmVal;
4402 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004403 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00004404 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbached6a0c52011-11-01 22:37:37 +00004405 if (CE) {
4406 int32_t Val = CE->getValue();
4407 if (isNegative && Val == 0)
4408 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Anderson63553c72011-08-29 17:17:09 +00004409 }
Sean Callanan76264762010-04-02 22:27:05 +00004410 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004411 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4412 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00004413 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004414 case AsmToken::Colon: {
4415 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00004416 // FIXME: Check it's an expression prefix,
4417 // e.g. (FOO - :lower16:BAR) isn't legal.
4418 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004419 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004420 return true;
4421
Evan Cheng75972122011-01-13 07:58:56 +00004422 const MCExpr *SubExprVal;
4423 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004424 return true;
4425
Evan Cheng75972122011-01-13 07:58:56 +00004426 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4427 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00004428 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00004429 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00004430 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004431 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004432 }
4433}
4434
Jim Grosbach1355cf12011-07-26 17:10:22 +00004435// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00004436// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004437bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00004438 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004439
4440 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00004441 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00004442 Parser.Lex(); // Eat ':'
4443
4444 if (getLexer().isNot(AsmToken::Identifier)) {
4445 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4446 return true;
4447 }
4448
4449 StringRef IDVal = Parser.getTok().getIdentifier();
4450 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00004451 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004452 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00004453 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004454 } else {
4455 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4456 return true;
4457 }
4458 Parser.Lex();
4459
4460 if (getLexer().isNot(AsmToken::Colon)) {
4461 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4462 return true;
4463 }
4464 Parser.Lex(); // Eat the last ':'
4465 return false;
4466}
4467
Daniel Dunbar352e1482011-01-11 15:59:50 +00004468/// \brief Given a mnemonic, split out possible predication code and carry
4469/// setting letters to form a canonical mnemonic and flags.
4470//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004471// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00004472// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004473StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00004474 unsigned &PredicationCode,
4475 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004476 unsigned &ProcessorIMod,
4477 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004478 PredicationCode = ARMCC::AL;
4479 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004480 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004481
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004482 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00004483 //
4484 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00004485 if ((Mnemonic == "movs" && isThumb()) ||
4486 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4487 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4488 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4489 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4490 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4491 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
Jim Grosbach68490192011-12-19 19:43:50 +00004492 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" ||
4493 Mnemonic == "fmuls")
Daniel Dunbar352e1482011-01-11 15:59:50 +00004494 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00004495
Jim Grosbach3f00e312011-07-11 17:09:57 +00004496 // First, split out any predication code. Ignore mnemonics we know aren't
4497 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00004498 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00004499 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00004500 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00004501 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00004502 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4503 .Case("eq", ARMCC::EQ)
4504 .Case("ne", ARMCC::NE)
4505 .Case("hs", ARMCC::HS)
4506 .Case("cs", ARMCC::HS)
4507 .Case("lo", ARMCC::LO)
4508 .Case("cc", ARMCC::LO)
4509 .Case("mi", ARMCC::MI)
4510 .Case("pl", ARMCC::PL)
4511 .Case("vs", ARMCC::VS)
4512 .Case("vc", ARMCC::VC)
4513 .Case("hi", ARMCC::HI)
4514 .Case("ls", ARMCC::LS)
4515 .Case("ge", ARMCC::GE)
4516 .Case("lt", ARMCC::LT)
4517 .Case("gt", ARMCC::GT)
4518 .Case("le", ARMCC::LE)
4519 .Case("al", ARMCC::AL)
4520 .Default(~0U);
4521 if (CC != ~0U) {
4522 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4523 PredicationCode = CC;
4524 }
Bill Wendling52925b62010-10-29 23:50:21 +00004525 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004526
Daniel Dunbar352e1482011-01-11 15:59:50 +00004527 // Next, determine if we have a carry setting bit. We explicitly ignore all
4528 // the instructions we know end in 's'.
4529 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00004530 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00004531 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4532 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4533 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach67ca1ad2011-12-08 00:49:29 +00004534 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach48171e72011-12-10 00:01:02 +00004535 Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
Jim Grosbach9c397892011-12-19 19:02:41 +00004536 Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" ||
Jim Grosbach1aa149f2011-12-22 19:20:45 +00004537 Mnemonic == "fmuls" || Mnemonic == "fcmps" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00004538 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004539 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4540 CarrySetting = true;
4541 }
4542
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004543 // The "cps" instruction can have a interrupt mode operand which is glued into
4544 // the mnemonic. Check if this is the case, split it and parse the imod op
4545 if (Mnemonic.startswith("cps")) {
4546 // Split out any imod code.
4547 unsigned IMod =
4548 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4549 .Case("ie", ARM_PROC::IE)
4550 .Case("id", ARM_PROC::ID)
4551 .Default(~0U);
4552 if (IMod != ~0U) {
4553 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4554 ProcessorIMod = IMod;
4555 }
4556 }
4557
Jim Grosbach89df9962011-08-26 21:43:41 +00004558 // The "it" instruction has the condition mask on the end of the mnemonic.
4559 if (Mnemonic.startswith("it")) {
4560 ITMask = Mnemonic.slice(2, Mnemonic.size());
4561 Mnemonic = Mnemonic.slice(0, 2);
4562 }
4563
Daniel Dunbar352e1482011-01-11 15:59:50 +00004564 return Mnemonic;
4565}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004566
4567/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4568/// inclusion of carry set or predication code operands.
4569//
4570// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004571void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00004572getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004573 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004574 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4575 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004576 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004577 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004578 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004579 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004580 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004581 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004582 Mnemonic == "mla" || Mnemonic == "smlal" ||
4583 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004584 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004585 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004586 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004587
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004588 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4589 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4590 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4591 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004592 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4593 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004594 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004595 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4596 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4597 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004598 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4599 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004600 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004601 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004602 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004603 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004604
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004605 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004606 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004607 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004608 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004609 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004610}
4611
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004612bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4613 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004614 // FIXME: This is all horribly hacky. We really need a better way to deal
4615 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004616
4617 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4618 // another does not. Specifically, the MOVW instruction does not. So we
4619 // special case it here and remove the defaulted (non-setting) cc_out
4620 // operand if that's the instruction we're trying to match.
4621 //
4622 // We do this as post-processing of the explicit operands rather than just
4623 // conditionally adding the cc_out in the first place because we need
4624 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004625 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004626 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4627 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4628 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4629 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004630
4631 // Register-register 'add' for thumb does not have a cc_out operand
4632 // when there are only two register operands.
4633 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4634 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4635 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4636 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4637 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004638 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004639 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4640 // have to check the immediate range here since Thumb2 has a variant
4641 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004642 if (((isThumb() && Mnemonic == "add") ||
4643 (isThumbTwo() && Mnemonic == "sub")) &&
4644 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004645 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4646 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4647 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004648 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4649 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4650 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004651 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004652 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4653 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004654 // selecting via the generic "add" mnemonic, so to know that we
4655 // should remove the cc_out operand, we have to explicitly check that
4656 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004657 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4658 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004659 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4660 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4661 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4662 // Nest conditions rather than one big 'if' statement for readability.
4663 //
4664 // If either register is a high reg, it's either one of the SP
4665 // variants (handled above) or a 32-bit encoding, so we just
Jim Grosbach12a88632012-01-21 00:07:56 +00004666 // check against T3. If the second register is the PC, this is an
4667 // alternate form of ADR, which uses encoding T4, so check for that too.
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004668 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4669 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
Jim Grosbach12a88632012-01-21 00:07:56 +00004670 static_cast<ARMOperand*>(Operands[4])->getReg() != ARM::PC &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004671 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4672 return false;
4673 // If both registers are low, we're in an IT block, and the immediate is
4674 // in range, we should use encoding T1 instead, which has a cc_out.
4675 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004676 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004677 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4678 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4679 return false;
4680
4681 // Otherwise, we use encoding T4, which does not have a cc_out
4682 // operand.
4683 return true;
4684 }
4685
Jim Grosbach64944f42011-09-14 21:00:40 +00004686 // The thumb2 multiply instruction doesn't have a CCOut register, so
4687 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4688 // use the 16-bit encoding or not.
4689 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4690 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4691 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4692 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4693 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4694 // If the registers aren't low regs, the destination reg isn't the
4695 // same as one of the source regs, or the cc_out operand is zero
4696 // outside of an IT block, we have to use the 32-bit encoding, so
4697 // remove the cc_out operand.
4698 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4699 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach1de0bd12011-11-15 19:29:45 +00004700 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach64944f42011-09-14 21:00:40 +00004701 !inITBlock() ||
4702 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4703 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4704 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4705 static_cast<ARMOperand*>(Operands[4])->getReg())))
4706 return true;
4707
Jim Grosbach7f1ec952011-11-15 19:55:16 +00004708 // Also check the 'mul' syntax variant that doesn't specify an explicit
4709 // destination register.
4710 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4711 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4712 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4713 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4714 // If the registers aren't low regs or the cc_out operand is zero
4715 // outside of an IT block, we have to use the 32-bit encoding, so
4716 // remove the cc_out operand.
4717 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4718 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4719 !inITBlock()))
4720 return true;
4721
Jim Grosbach64944f42011-09-14 21:00:40 +00004722
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004723
Jim Grosbachf69c8042011-08-24 21:42:27 +00004724 // Register-register 'add/sub' for thumb does not have a cc_out operand
4725 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4726 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4727 // right, this will result in better diagnostics (which operand is off)
4728 // anyway.
4729 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4730 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004731 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4732 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4733 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4734 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004735
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004736 return false;
4737}
4738
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004739static bool isDataTypeToken(StringRef Tok) {
4740 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4741 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4742 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4743 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4744 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4745 Tok == ".f" || Tok == ".d";
4746}
4747
4748// FIXME: This bit should probably be handled via an explicit match class
4749// in the .td files that matches the suffix instead of having it be
4750// a literal string token the way it is now.
4751static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4752 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4753}
4754
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004755static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004756/// Parse an arm instruction mnemonic followed by its operands.
4757bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4758 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004759 // Apply mnemonic aliases before doing anything else, as the destination
4760 // mnemnonic may include suffices and we want to handle them normally.
4761 // The generic tblgen'erated code does this later, at the start of
4762 // MatchInstructionImpl(), but that's too late for aliases that include
4763 // any sort of suffix.
4764 unsigned AvailableFeatures = getAvailableFeatures();
4765 applyMnemonicAliases(Name, AvailableFeatures);
4766
Jim Grosbacha39cda72011-12-14 02:16:11 +00004767 // First check for the ARM-specific .req directive.
4768 if (Parser.getTok().is(AsmToken::Identifier) &&
4769 Parser.getTok().getIdentifier() == ".req") {
4770 parseDirectiveReq(Name, NameLoc);
4771 // We always return 'error' for this, as we're done with this
4772 // statement and don't need to match the 'instruction."
4773 return true;
4774 }
4775
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004776 // Create the leading tokens for the mnemonic, split by '.' characters.
4777 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004778 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004779
Daniel Dunbar352e1482011-01-11 15:59:50 +00004780 // Split out the predication code and carry setting flag from the mnemonic.
4781 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004782 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004783 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004784 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004785 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004786 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004787
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004788 // In Thumb1, only the branch (B) instruction can be predicated.
4789 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4790 Parser.EatToEndOfStatement();
4791 return Error(NameLoc, "conditional execution not supported in Thumb1");
4792 }
4793
Jim Grosbachffa32252011-07-19 19:13:28 +00004794 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4795
Jim Grosbach89df9962011-08-26 21:43:41 +00004796 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4797 // is the mask as it will be for the IT encoding if the conditional
4798 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4799 // where the conditional bit0 is zero, the instruction post-processing
4800 // will adjust the mask accordingly.
4801 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004802 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4803 if (ITMask.size() > 3) {
4804 Parser.EatToEndOfStatement();
4805 return Error(Loc, "too many conditions on IT instruction");
4806 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004807 unsigned Mask = 8;
4808 for (unsigned i = ITMask.size(); i != 0; --i) {
4809 char pos = ITMask[i - 1];
4810 if (pos != 't' && pos != 'e') {
4811 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004812 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004813 }
4814 Mask >>= 1;
4815 if (ITMask[i - 1] == 't')
4816 Mask |= 8;
4817 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004818 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004819 }
4820
Jim Grosbachffa32252011-07-19 19:13:28 +00004821 // FIXME: This is all a pretty gross hack. We should automatically handle
4822 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004823
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004824 // Next, add the CCOut and ConditionCode operands, if needed.
4825 //
4826 // For mnemonics which can ever incorporate a carry setting bit or predication
4827 // code, our matching model involves us always generating CCOut and
4828 // ConditionCode operands to match the mnemonic "as written" and then we let
4829 // the matcher deal with finding the right instruction or generating an
4830 // appropriate error.
4831 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004832 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004833
Jim Grosbach33c16a22011-07-14 22:04:21 +00004834 // If we had a carry-set on an instruction that can't do that, issue an
4835 // error.
4836 if (!CanAcceptCarrySet && CarrySetting) {
4837 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004838 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004839 "' can not set flags, but 's' suffix specified");
4840 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004841 // If we had a predication code on an instruction that can't do that, issue an
4842 // error.
4843 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4844 Parser.EatToEndOfStatement();
4845 return Error(NameLoc, "instruction '" + Mnemonic +
4846 "' is not predicable, but condition code specified");
4847 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004848
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004849 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004850 if (CanAcceptCarrySet) {
4851 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004852 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004853 Loc));
4854 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004855
4856 // Add the predication code operand, if necessary.
4857 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004858 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4859 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004860 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004861 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004862 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004863
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004864 // Add the processor imod operand, if necessary.
4865 if (ProcessorIMod) {
4866 Operands.push_back(ARMOperand::CreateImm(
4867 MCConstantExpr::Create(ProcessorIMod, getContext()),
4868 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004869 }
4870
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004871 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004872 while (Next != StringRef::npos) {
4873 Start = Next;
4874 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004875 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004876
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004877 // Some NEON instructions have an optional datatype suffix that is
4878 // completely ignored. Check for that.
4879 if (isDataTypeToken(ExtraToken) &&
4880 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4881 continue;
4882
Jim Grosbach81d2e392011-09-07 16:06:04 +00004883 if (ExtraToken != ".n") {
4884 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4885 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4886 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004887 }
4888
4889 // Read the remaining operands.
4890 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004891 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004892 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004893 Parser.EatToEndOfStatement();
4894 return true;
4895 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004896
4897 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004898 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004899
4900 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004901 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004902 Parser.EatToEndOfStatement();
4903 return true;
4904 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004905 }
4906 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004907
Chris Lattnercbf8a982010-09-11 16:18:25 +00004908 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004909 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004910 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004911 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004912 }
Bill Wendling146018f2010-11-06 21:42:12 +00004913
Chris Lattner34e53142010-09-08 05:10:46 +00004914 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004915
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004916 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4917 // do and don't have a cc_out optional-def operand. With some spot-checks
4918 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004919 // parse and adjust accordingly before actually matching. We shouldn't ever
4920 // try to remove a cc_out operand that was explicitly set on the the
4921 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4922 // table driven matcher doesn't fit well with the ARM instruction set.
4923 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004924 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4925 Operands.erase(Operands.begin() + 1);
4926 delete Op;
4927 }
4928
Jim Grosbachcf121c32011-07-28 21:57:55 +00004929 // ARM mode 'blx' need special handling, as the register operand version
4930 // is predicable, but the label operand version is not. So, we can't rely
4931 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004932 // a k_CondCode operand in the list. If we're trying to match the label
4933 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004934 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4935 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4936 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4937 Operands.erase(Operands.begin() + 1);
4938 delete Op;
4939 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00004940
4941 // The vector-compare-to-zero instructions have a literal token "#0" at
4942 // the end that comes to here as an immediate operand. Convert it to a
4943 // token to play nicely with the matcher.
4944 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4945 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4946 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4947 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4948 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4949 if (CE && CE->getValue() == 0) {
4950 Operands.erase(Operands.begin() + 5);
4951 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4952 delete Op;
4953 }
4954 }
Jim Grosbach68259142011-10-03 22:30:24 +00004955 // VCMP{E} does the same thing, but with a different operand count.
4956 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4957 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4958 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4959 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4960 if (CE && CE->getValue() == 0) {
4961 Operands.erase(Operands.begin() + 4);
4962 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4963 delete Op;
4964 }
4965 }
Jim Grosbach934755a2011-08-22 23:47:13 +00004966 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
Jim Grosbach55b02f22011-12-13 20:50:38 +00004967 // end. Convert it to a token here. Take care not to convert those
4968 // that should hit the Thumb2 encoding.
Jim Grosbach934755a2011-08-22 23:47:13 +00004969 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
Jim Grosbach55b02f22011-12-13 20:50:38 +00004970 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4971 static_cast<ARMOperand*>(Operands[4])->isReg() &&
Jim Grosbach934755a2011-08-22 23:47:13 +00004972 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4973 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4974 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
Jim Grosbach55b02f22011-12-13 20:50:38 +00004975 if (CE && CE->getValue() == 0 &&
4976 (isThumbOne() ||
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00004977 // The cc_out operand matches the IT block.
4978 ((inITBlock() != CarrySetting) &&
4979 // Neither register operand is a high register.
Jim Grosbach55b02f22011-12-13 20:50:38 +00004980 (isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00004981 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()))))){
Jim Grosbach934755a2011-08-22 23:47:13 +00004982 Operands.erase(Operands.begin() + 5);
4983 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4984 delete Op;
4985 }
4986 }
4987
Chris Lattner98986712010-01-14 22:21:20 +00004988 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004989}
4990
Jim Grosbach189610f2011-07-26 18:25:39 +00004991// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004992
4993// return 'true' if register list contains non-low GPR registers,
4994// 'false' otherwise. If Reg is in the register list or is HiReg, set
4995// 'containsReg' to true.
4996static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4997 unsigned HiReg, bool &containsReg) {
4998 containsReg = false;
4999 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5000 unsigned OpReg = Inst.getOperand(i).getReg();
5001 if (OpReg == Reg)
5002 containsReg = true;
5003 // Anything other than a low register isn't legal here.
5004 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
5005 return true;
5006 }
5007 return false;
5008}
5009
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005010// Check if the specified regisgter is in the register list of the inst,
5011// starting at the indicated operand number.
5012static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
5013 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5014 unsigned OpReg = Inst.getOperand(i).getReg();
5015 if (OpReg == Reg)
5016 return true;
5017 }
5018 return false;
5019}
5020
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005021// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
5022// the ARMInsts array) instead. Getting that here requires awkward
5023// API changes, though. Better way?
5024namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005025extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005026}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005027static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005028 return ARMInsts[Opcode];
5029}
5030
Jim Grosbach189610f2011-07-26 18:25:39 +00005031// FIXME: We would really like to be able to tablegen'erate this.
5032bool ARMAsmParser::
5033validateInstruction(MCInst &Inst,
5034 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005035 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005036 SMLoc Loc = Operands[0]->getStartLoc();
5037 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00005038 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
5039 // being allowed in IT blocks, but not being predicable. It just always
5040 // executes.
5041 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005042 unsigned bit = 1;
5043 if (ITState.FirstCond)
5044 ITState.FirstCond = false;
5045 else
Jim Grosbacha1109882011-09-02 23:22:08 +00005046 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005047 // The instruction must be predicable.
5048 if (!MCID.isPredicable())
5049 return Error(Loc, "instructions in IT block must be predicable");
5050 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
5051 unsigned ITCond = bit ? ITState.Cond :
5052 ARMCC::getOppositeCondition(ITState.Cond);
5053 if (Cond != ITCond) {
5054 // Find the condition code Operand to get its SMLoc information.
5055 SMLoc CondLoc;
5056 for (unsigned i = 1; i < Operands.size(); ++i)
5057 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
5058 CondLoc = Operands[i]->getStartLoc();
5059 return Error(CondLoc, "incorrect condition in IT block; got '" +
5060 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
5061 "', but expected '" +
5062 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
5063 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00005064 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005065 } else if (isThumbTwo() && MCID.isPredicable() &&
5066 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005067 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
5068 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005069 return Error(Loc, "predicated instructions must be in IT block");
5070
Jim Grosbach189610f2011-07-26 18:25:39 +00005071 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00005072 case ARM::LDRD:
5073 case ARM::LDRD_PRE:
5074 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005075 case ARM::LDREXD: {
5076 // Rt2 must be Rt + 1.
5077 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5078 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5079 if (Rt2 != Rt + 1)
5080 return Error(Operands[3]->getStartLoc(),
5081 "destination operands must be sequential");
5082 return false;
5083 }
Jim Grosbach14605d12011-08-11 20:28:23 +00005084 case ARM::STRD: {
5085 // Rt2 must be Rt + 1.
5086 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5087 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5088 if (Rt2 != Rt + 1)
5089 return Error(Operands[3]->getStartLoc(),
5090 "source operands must be sequential");
5091 return false;
5092 }
Jim Grosbach53642c52011-08-10 20:49:18 +00005093 case ARM::STRD_PRE:
5094 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005095 case ARM::STREXD: {
5096 // Rt2 must be Rt + 1.
5097 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5098 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
5099 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00005100 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00005101 "source operands must be sequential");
5102 return false;
5103 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005104 case ARM::SBFX:
5105 case ARM::UBFX: {
5106 // width must be in range [1, 32-lsb]
5107 unsigned lsb = Inst.getOperand(2).getImm();
5108 unsigned widthm1 = Inst.getOperand(3).getImm();
5109 if (widthm1 >= 32 - lsb)
5110 return Error(Operands[5]->getStartLoc(),
5111 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00005112 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005113 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005114 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005115 // If we're parsing Thumb2, the .w variant is available and handles
5116 // most cases that are normally illegal for a Thumb1 LDM
5117 // instruction. We'll make the transformation in processInstruction()
5118 // if necessary.
5119 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005120 // Thumb LDM instructions are writeback iff the base register is not
5121 // in the register list.
5122 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005123 bool hasWritebackToken =
5124 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5125 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00005126 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005127 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005128 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
5129 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005130 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005131 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005132 return Error(Operands[2]->getStartLoc(),
5133 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005134 // If we should not have writeback, there must not be a '!'. This is
5135 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00005136 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005137 return Error(Operands[3]->getStartLoc(),
5138 "writeback operator '!' not allowed when base register "
5139 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005140
5141 break;
5142 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005143 case ARM::t2LDMIA_UPD: {
5144 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
5145 return Error(Operands[4]->getStartLoc(),
5146 "writeback operator '!' not allowed when base register "
5147 "in register list");
5148 break;
5149 }
Jim Grosbach54026372011-11-10 23:17:11 +00005150 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
5151 // so only issue a diagnostic for thumb1. The instructions will be
5152 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005153 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005154 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005155 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
5156 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005157 return Error(Operands[2]->getStartLoc(),
5158 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005159 break;
5160 }
5161 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005162 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005163 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
5164 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005165 return Error(Operands[2]->getStartLoc(),
5166 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005167 break;
5168 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00005169 case ARM::tSTMIA_UPD: {
5170 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00005171 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00005172 return Error(Operands[4]->getStartLoc(),
5173 "registers must be in range r0-r7");
5174 break;
5175 }
Jim Grosbach189610f2011-07-26 18:25:39 +00005176 }
5177
5178 return false;
5179}
5180
Jim Grosbachd7433e22012-01-23 23:45:44 +00005181static unsigned getRealVSTOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach84defb52011-12-02 22:34:51 +00005182 switch(Opc) {
5183 default: assert(0 && "unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005184 // VST1LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005185 case ARM::VST1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
5186 case ARM::VST1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
5187 case ARM::VST1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
5188 case ARM::VST1LNdWB_register_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
5189 case ARM::VST1LNdWB_register_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
5190 case ARM::VST1LNdWB_register_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
5191 case ARM::VST1LNdAsm_8: Spacing = 1; return ARM::VST1LNd8;
5192 case ARM::VST1LNdAsm_16: Spacing = 1; return ARM::VST1LNd16;
5193 case ARM::VST1LNdAsm_32: Spacing = 1; return ARM::VST1LNd32;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005194
5195 // VST2LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005196 case ARM::VST2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
5197 case ARM::VST2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
5198 case ARM::VST2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
5199 case ARM::VST2LNqWB_fixed_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
5200 case ARM::VST2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005201
Jim Grosbach7945ead2012-01-24 00:43:12 +00005202 case ARM::VST2LNdWB_register_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
5203 case ARM::VST2LNdWB_register_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
5204 case ARM::VST2LNdWB_register_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
5205 case ARM::VST2LNqWB_register_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
5206 case ARM::VST2LNqWB_register_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005207
Jim Grosbach7945ead2012-01-24 00:43:12 +00005208 case ARM::VST2LNdAsm_8: Spacing = 1; return ARM::VST2LNd8;
5209 case ARM::VST2LNdAsm_16: Spacing = 1; return ARM::VST2LNd16;
5210 case ARM::VST2LNdAsm_32: Spacing = 1; return ARM::VST2LNd32;
5211 case ARM::VST2LNqAsm_16: Spacing = 2; return ARM::VST2LNq16;
5212 case ARM::VST2LNqAsm_32: Spacing = 2; return ARM::VST2LNq32;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005213
Jim Grosbach4adb1822012-01-24 00:07:41 +00005214 // VST3LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005215 case ARM::VST3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
5216 case ARM::VST3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
5217 case ARM::VST3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
5218 case ARM::VST3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNq16_UPD;
5219 case ARM::VST3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
5220 case ARM::VST3LNdWB_register_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
5221 case ARM::VST3LNdWB_register_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
5222 case ARM::VST3LNdWB_register_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
5223 case ARM::VST3LNqWB_register_Asm_16: Spacing = 2; return ARM::VST3LNq16_UPD;
5224 case ARM::VST3LNqWB_register_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
5225 case ARM::VST3LNdAsm_8: Spacing = 1; return ARM::VST3LNd8;
5226 case ARM::VST3LNdAsm_16: Spacing = 1; return ARM::VST3LNd16;
5227 case ARM::VST3LNdAsm_32: Spacing = 1; return ARM::VST3LNd32;
5228 case ARM::VST3LNqAsm_16: Spacing = 2; return ARM::VST3LNq16;
5229 case ARM::VST3LNqAsm_32: Spacing = 2; return ARM::VST3LNq32;
Jim Grosbach4adb1822012-01-24 00:07:41 +00005230
Jim Grosbachd7433e22012-01-23 23:45:44 +00005231 // VST3
Jim Grosbach7945ead2012-01-24 00:43:12 +00005232 case ARM::VST3dWB_fixed_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
5233 case ARM::VST3dWB_fixed_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
5234 case ARM::VST3dWB_fixed_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
5235 case ARM::VST3qWB_fixed_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
5236 case ARM::VST3qWB_fixed_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
5237 case ARM::VST3qWB_fixed_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
5238 case ARM::VST3dWB_register_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
5239 case ARM::VST3dWB_register_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
5240 case ARM::VST3dWB_register_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
5241 case ARM::VST3qWB_register_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
5242 case ARM::VST3qWB_register_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
5243 case ARM::VST3qWB_register_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
5244 case ARM::VST3dAsm_8: Spacing = 1; return ARM::VST3d8;
5245 case ARM::VST3dAsm_16: Spacing = 1; return ARM::VST3d16;
5246 case ARM::VST3dAsm_32: Spacing = 1; return ARM::VST3d32;
5247 case ARM::VST3qAsm_8: Spacing = 2; return ARM::VST3q8;
5248 case ARM::VST3qAsm_16: Spacing = 2; return ARM::VST3q16;
5249 case ARM::VST3qAsm_32: Spacing = 2; return ARM::VST3q32;
Jim Grosbach539aab72012-01-24 00:58:13 +00005250
5251 // VST4
5252 case ARM::VST4dWB_fixed_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
5253 case ARM::VST4dWB_fixed_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
5254 case ARM::VST4dWB_fixed_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
5255 case ARM::VST4qWB_fixed_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
5256 case ARM::VST4qWB_fixed_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
5257 case ARM::VST4qWB_fixed_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
5258 case ARM::VST4dWB_register_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
5259 case ARM::VST4dWB_register_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
5260 case ARM::VST4dWB_register_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
5261 case ARM::VST4qWB_register_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
5262 case ARM::VST4qWB_register_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
5263 case ARM::VST4qWB_register_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
5264 case ARM::VST4dAsm_8: Spacing = 1; return ARM::VST4d8;
5265 case ARM::VST4dAsm_16: Spacing = 1; return ARM::VST4d16;
5266 case ARM::VST4dAsm_32: Spacing = 1; return ARM::VST4d32;
5267 case ARM::VST4qAsm_8: Spacing = 2; return ARM::VST4q8;
5268 case ARM::VST4qAsm_16: Spacing = 2; return ARM::VST4q16;
5269 case ARM::VST4qAsm_32: Spacing = 2; return ARM::VST4q32;
Jim Grosbach84defb52011-12-02 22:34:51 +00005270 }
5271}
5272
Jim Grosbachd7433e22012-01-23 23:45:44 +00005273static unsigned getRealVLDOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005274 switch(Opc) {
5275 default: assert(0 && "unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005276 // VLD1LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005277 case ARM::VLD1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
5278 case ARM::VLD1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
5279 case ARM::VLD1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
5280 case ARM::VLD1LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
5281 case ARM::VLD1LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
5282 case ARM::VLD1LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
5283 case ARM::VLD1LNdAsm_8: Spacing = 1; return ARM::VLD1LNd8;
5284 case ARM::VLD1LNdAsm_16: Spacing = 1; return ARM::VLD1LNd16;
5285 case ARM::VLD1LNdAsm_32: Spacing = 1; return ARM::VLD1LNd32;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005286
5287 // VLD2LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005288 case ARM::VLD2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
5289 case ARM::VLD2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
5290 case ARM::VLD2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
5291 case ARM::VLD2LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNq16_UPD;
5292 case ARM::VLD2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
5293 case ARM::VLD2LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
5294 case ARM::VLD2LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
5295 case ARM::VLD2LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
5296 case ARM::VLD2LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD2LNq16_UPD;
5297 case ARM::VLD2LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
5298 case ARM::VLD2LNdAsm_8: Spacing = 1; return ARM::VLD2LNd8;
5299 case ARM::VLD2LNdAsm_16: Spacing = 1; return ARM::VLD2LNd16;
5300 case ARM::VLD2LNdAsm_32: Spacing = 1; return ARM::VLD2LNd32;
5301 case ARM::VLD2LNqAsm_16: Spacing = 2; return ARM::VLD2LNq16;
5302 case ARM::VLD2LNqAsm_32: Spacing = 2; return ARM::VLD2LNq32;
Jim Grosbach3a678af2012-01-23 21:53:26 +00005303
5304 // VLD3LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005305 case ARM::VLD3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
5306 case ARM::VLD3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
5307 case ARM::VLD3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
5308 case ARM::VLD3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNq16_UPD;
5309 case ARM::VLD3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
5310 case ARM::VLD3LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
5311 case ARM::VLD3LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
5312 case ARM::VLD3LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
5313 case ARM::VLD3LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD3LNq16_UPD;
5314 case ARM::VLD3LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
5315 case ARM::VLD3LNdAsm_8: Spacing = 1; return ARM::VLD3LNd8;
5316 case ARM::VLD3LNdAsm_16: Spacing = 1; return ARM::VLD3LNd16;
5317 case ARM::VLD3LNdAsm_32: Spacing = 1; return ARM::VLD3LNd32;
5318 case ARM::VLD3LNqAsm_16: Spacing = 2; return ARM::VLD3LNq16;
5319 case ARM::VLD3LNqAsm_32: Spacing = 2; return ARM::VLD3LNq32;
Jim Grosbachc387fc62012-01-23 23:20:46 +00005320
5321 // VLD3
Jim Grosbach7945ead2012-01-24 00:43:12 +00005322 case ARM::VLD3dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
5323 case ARM::VLD3dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
5324 case ARM::VLD3dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
5325 case ARM::VLD3qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
5326 case ARM::VLD3qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
5327 case ARM::VLD3qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
5328 case ARM::VLD3dWB_register_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
5329 case ARM::VLD3dWB_register_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
5330 case ARM::VLD3dWB_register_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
5331 case ARM::VLD3qWB_register_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
5332 case ARM::VLD3qWB_register_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
5333 case ARM::VLD3qWB_register_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
5334 case ARM::VLD3dAsm_8: Spacing = 1; return ARM::VLD3d8;
5335 case ARM::VLD3dAsm_16: Spacing = 1; return ARM::VLD3d16;
5336 case ARM::VLD3dAsm_32: Spacing = 1; return ARM::VLD3d32;
5337 case ARM::VLD3qAsm_8: Spacing = 2; return ARM::VLD3q8;
5338 case ARM::VLD3qAsm_16: Spacing = 2; return ARM::VLD3q16;
5339 case ARM::VLD3qAsm_32: Spacing = 2; return ARM::VLD3q32;
Jim Grosbach8abe7e32012-01-24 00:43:17 +00005340
5341 // VLD4
5342 case ARM::VLD4dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
5343 case ARM::VLD4dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
5344 case ARM::VLD4dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
5345 case ARM::VLD4qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
5346 case ARM::VLD4qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
5347 case ARM::VLD4qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
5348 case ARM::VLD4dWB_register_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
5349 case ARM::VLD4dWB_register_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
5350 case ARM::VLD4dWB_register_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
5351 case ARM::VLD4qWB_register_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
5352 case ARM::VLD4qWB_register_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
5353 case ARM::VLD4qWB_register_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
5354 case ARM::VLD4dAsm_8: Spacing = 1; return ARM::VLD4d8;
5355 case ARM::VLD4dAsm_16: Spacing = 1; return ARM::VLD4d16;
5356 case ARM::VLD4dAsm_32: Spacing = 1; return ARM::VLD4d32;
5357 case ARM::VLD4qAsm_8: Spacing = 2; return ARM::VLD4q8;
5358 case ARM::VLD4qAsm_16: Spacing = 2; return ARM::VLD4q16;
5359 case ARM::VLD4qAsm_32: Spacing = 2; return ARM::VLD4q32;
Jim Grosbach7636bf62011-12-02 00:35:16 +00005360 }
5361}
5362
Jim Grosbach83ec8772011-11-10 23:42:14 +00005363bool ARMAsmParser::
Jim Grosbachf8fce712011-08-11 17:35:48 +00005364processInstruction(MCInst &Inst,
5365 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5366 switch (Inst.getOpcode()) {
Jim Grosbach0b4c6732012-01-18 22:46:46 +00005367 // Aliases for alternate PC+imm syntax of LDR instructions.
5368 case ARM::t2LDRpcrel:
5369 Inst.setOpcode(ARM::t2LDRpci);
5370 return true;
5371 case ARM::t2LDRBpcrel:
5372 Inst.setOpcode(ARM::t2LDRBpci);
5373 return true;
5374 case ARM::t2LDRHpcrel:
5375 Inst.setOpcode(ARM::t2LDRHpci);
5376 return true;
5377 case ARM::t2LDRSBpcrel:
5378 Inst.setOpcode(ARM::t2LDRSBpci);
5379 return true;
5380 case ARM::t2LDRSHpcrel:
5381 Inst.setOpcode(ARM::t2LDRSHpci);
5382 return true;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005383 // Handle NEON VST complex aliases.
Jim Grosbach8b31f952012-01-23 19:39:08 +00005384 case ARM::VST1LNdWB_register_Asm_8:
5385 case ARM::VST1LNdWB_register_Asm_16:
5386 case ARM::VST1LNdWB_register_Asm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005387 MCInst TmpInst;
5388 // Shuffle the operands around so the lane index operand is in the
5389 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005390 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005391 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005392 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5393 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5394 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5395 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5396 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5397 TmpInst.addOperand(Inst.getOperand(1)); // lane
5398 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5399 TmpInst.addOperand(Inst.getOperand(6));
5400 Inst = TmpInst;
5401 return true;
5402 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005403
Jim Grosbach8b31f952012-01-23 19:39:08 +00005404 case ARM::VST2LNdWB_register_Asm_8:
5405 case ARM::VST2LNdWB_register_Asm_16:
5406 case ARM::VST2LNdWB_register_Asm_32:
5407 case ARM::VST2LNqWB_register_Asm_16:
5408 case ARM::VST2LNqWB_register_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005409 MCInst TmpInst;
5410 // Shuffle the operands around so the lane index operand is in the
5411 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005412 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005413 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005414 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5415 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5416 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5417 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5418 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005419 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5420 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005421 TmpInst.addOperand(Inst.getOperand(1)); // lane
5422 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5423 TmpInst.addOperand(Inst.getOperand(6));
5424 Inst = TmpInst;
5425 return true;
5426 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005427
5428 case ARM::VST3LNdWB_register_Asm_8:
5429 case ARM::VST3LNdWB_register_Asm_16:
5430 case ARM::VST3LNdWB_register_Asm_32:
5431 case ARM::VST3LNqWB_register_Asm_16:
5432 case ARM::VST3LNqWB_register_Asm_32: {
5433 MCInst TmpInst;
5434 // Shuffle the operands around so the lane index operand is in the
5435 // right place.
5436 unsigned Spacing;
5437 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5438 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5439 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5440 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5441 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5442 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5443 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5444 Spacing));
5445 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5446 Spacing * 2));
5447 TmpInst.addOperand(Inst.getOperand(1)); // lane
5448 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5449 TmpInst.addOperand(Inst.getOperand(6));
5450 Inst = TmpInst;
5451 return true;
5452 }
5453
Jim Grosbach8b31f952012-01-23 19:39:08 +00005454 case ARM::VST1LNdWB_fixed_Asm_8:
5455 case ARM::VST1LNdWB_fixed_Asm_16:
5456 case ARM::VST1LNdWB_fixed_Asm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005457 MCInst TmpInst;
5458 // Shuffle the operands around so the lane index operand is in the
5459 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005460 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005461 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005462 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5463 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5464 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5465 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5466 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5467 TmpInst.addOperand(Inst.getOperand(1)); // lane
5468 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5469 TmpInst.addOperand(Inst.getOperand(5));
5470 Inst = TmpInst;
5471 return true;
5472 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005473
Jim Grosbach8b31f952012-01-23 19:39:08 +00005474 case ARM::VST2LNdWB_fixed_Asm_8:
5475 case ARM::VST2LNdWB_fixed_Asm_16:
5476 case ARM::VST2LNdWB_fixed_Asm_32:
5477 case ARM::VST2LNqWB_fixed_Asm_16:
5478 case ARM::VST2LNqWB_fixed_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005479 MCInst TmpInst;
5480 // Shuffle the operands around so the lane index operand is in the
5481 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005482 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005483 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005484 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5485 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5486 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5487 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5488 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005489 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5490 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005491 TmpInst.addOperand(Inst.getOperand(1)); // lane
5492 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5493 TmpInst.addOperand(Inst.getOperand(5));
5494 Inst = TmpInst;
5495 return true;
5496 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005497
5498 case ARM::VST3LNdWB_fixed_Asm_8:
5499 case ARM::VST3LNdWB_fixed_Asm_16:
5500 case ARM::VST3LNdWB_fixed_Asm_32:
5501 case ARM::VST3LNqWB_fixed_Asm_16:
5502 case ARM::VST3LNqWB_fixed_Asm_32: {
5503 MCInst TmpInst;
5504 // Shuffle the operands around so the lane index operand is in the
5505 // right place.
5506 unsigned Spacing;
5507 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5508 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5509 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5510 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5511 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5512 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5513 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5514 Spacing));
5515 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5516 Spacing * 2));
5517 TmpInst.addOperand(Inst.getOperand(1)); // lane
5518 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5519 TmpInst.addOperand(Inst.getOperand(5));
5520 Inst = TmpInst;
5521 return true;
5522 }
5523
Jim Grosbach8b31f952012-01-23 19:39:08 +00005524 case ARM::VST1LNdAsm_8:
5525 case ARM::VST1LNdAsm_16:
5526 case ARM::VST1LNdAsm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005527 MCInst TmpInst;
5528 // Shuffle the operands around so the lane index operand is in the
5529 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005530 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005531 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005532 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5533 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5534 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5535 TmpInst.addOperand(Inst.getOperand(1)); // lane
5536 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5537 TmpInst.addOperand(Inst.getOperand(5));
5538 Inst = TmpInst;
5539 return true;
5540 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005541
Jim Grosbach8b31f952012-01-23 19:39:08 +00005542 case ARM::VST2LNdAsm_8:
5543 case ARM::VST2LNdAsm_16:
5544 case ARM::VST2LNdAsm_32:
5545 case ARM::VST2LNqAsm_16:
5546 case ARM::VST2LNqAsm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005547 MCInst TmpInst;
5548 // Shuffle the operands around so the lane index operand is in the
5549 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005550 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005551 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005552 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5553 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5554 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005555 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5556 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005557 TmpInst.addOperand(Inst.getOperand(1)); // lane
5558 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5559 TmpInst.addOperand(Inst.getOperand(5));
5560 Inst = TmpInst;
5561 return true;
5562 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005563
5564 case ARM::VST3LNdAsm_8:
5565 case ARM::VST3LNdAsm_16:
5566 case ARM::VST3LNdAsm_32:
5567 case ARM::VST3LNqAsm_16:
5568 case ARM::VST3LNqAsm_32: {
5569 MCInst TmpInst;
5570 // Shuffle the operands around so the lane index operand is in the
5571 // right place.
5572 unsigned Spacing;
5573 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5574 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5575 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5576 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5577 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5578 Spacing));
5579 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5580 Spacing * 2));
5581 TmpInst.addOperand(Inst.getOperand(1)); // lane
5582 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5583 TmpInst.addOperand(Inst.getOperand(5));
5584 Inst = TmpInst;
5585 return true;
5586 }
5587
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005588 // Handle NEON VLD complex aliases.
Jim Grosbach8b31f952012-01-23 19:39:08 +00005589 case ARM::VLD1LNdWB_register_Asm_8:
5590 case ARM::VLD1LNdWB_register_Asm_16:
5591 case ARM::VLD1LNdWB_register_Asm_32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005592 MCInst TmpInst;
5593 // Shuffle the operands around so the lane index operand is in the
5594 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005595 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005596 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005597 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5598 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5599 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5600 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5601 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5602 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5603 TmpInst.addOperand(Inst.getOperand(1)); // lane
5604 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5605 TmpInst.addOperand(Inst.getOperand(6));
5606 Inst = TmpInst;
5607 return true;
5608 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005609
Jim Grosbach8b31f952012-01-23 19:39:08 +00005610 case ARM::VLD2LNdWB_register_Asm_8:
5611 case ARM::VLD2LNdWB_register_Asm_16:
5612 case ARM::VLD2LNdWB_register_Asm_32:
5613 case ARM::VLD2LNqWB_register_Asm_16:
5614 case ARM::VLD2LNqWB_register_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005615 MCInst TmpInst;
5616 // Shuffle the operands around so the lane index operand is in the
5617 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005618 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005619 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005620 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005621 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5622 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005623 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5624 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5625 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5626 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5627 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005628 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5629 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005630 TmpInst.addOperand(Inst.getOperand(1)); // lane
5631 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5632 TmpInst.addOperand(Inst.getOperand(6));
5633 Inst = TmpInst;
5634 return true;
5635 }
5636
Jim Grosbach3a678af2012-01-23 21:53:26 +00005637 case ARM::VLD3LNdWB_register_Asm_8:
5638 case ARM::VLD3LNdWB_register_Asm_16:
5639 case ARM::VLD3LNdWB_register_Asm_32:
5640 case ARM::VLD3LNqWB_register_Asm_16:
5641 case ARM::VLD3LNqWB_register_Asm_32: {
5642 MCInst TmpInst;
5643 // Shuffle the operands around so the lane index operand is in the
5644 // right place.
5645 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005646 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005647 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5648 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5649 Spacing));
5650 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005651 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005652 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5653 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5654 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5655 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5656 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5657 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5658 Spacing));
5659 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005660 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005661 TmpInst.addOperand(Inst.getOperand(1)); // lane
5662 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5663 TmpInst.addOperand(Inst.getOperand(6));
5664 Inst = TmpInst;
5665 return true;
5666 }
5667
Jim Grosbach8b31f952012-01-23 19:39:08 +00005668 case ARM::VLD1LNdWB_fixed_Asm_8:
5669 case ARM::VLD1LNdWB_fixed_Asm_16:
5670 case ARM::VLD1LNdWB_fixed_Asm_32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005671 MCInst TmpInst;
5672 // Shuffle the operands around so the lane index operand is in the
5673 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005674 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005675 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005676 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5677 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5678 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5679 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5680 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5681 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5682 TmpInst.addOperand(Inst.getOperand(1)); // lane
5683 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5684 TmpInst.addOperand(Inst.getOperand(5));
5685 Inst = TmpInst;
5686 return true;
5687 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005688
Jim Grosbach8b31f952012-01-23 19:39:08 +00005689 case ARM::VLD2LNdWB_fixed_Asm_8:
5690 case ARM::VLD2LNdWB_fixed_Asm_16:
5691 case ARM::VLD2LNdWB_fixed_Asm_32:
5692 case ARM::VLD2LNqWB_fixed_Asm_16:
5693 case ARM::VLD2LNqWB_fixed_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005694 MCInst TmpInst;
5695 // Shuffle the operands around so the lane index operand is in the
5696 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005697 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005698 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005699 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005700 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5701 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +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)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005707 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5708 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005709 TmpInst.addOperand(Inst.getOperand(1)); // lane
5710 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5711 TmpInst.addOperand(Inst.getOperand(5));
5712 Inst = TmpInst;
5713 return true;
5714 }
5715
Jim Grosbach3a678af2012-01-23 21:53:26 +00005716 case ARM::VLD3LNdWB_fixed_Asm_8:
5717 case ARM::VLD3LNdWB_fixed_Asm_16:
5718 case ARM::VLD3LNdWB_fixed_Asm_32:
5719 case ARM::VLD3LNqWB_fixed_Asm_16:
5720 case ARM::VLD3LNqWB_fixed_Asm_32: {
5721 MCInst TmpInst;
5722 // Shuffle the operands around so the lane index operand is in the
5723 // right place.
5724 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005725 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005726 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5727 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5728 Spacing));
5729 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005730 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005731 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5732 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5733 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5734 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5735 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5736 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5737 Spacing));
5738 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005739 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005740 TmpInst.addOperand(Inst.getOperand(1)); // lane
5741 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5742 TmpInst.addOperand(Inst.getOperand(5));
5743 Inst = TmpInst;
5744 return true;
5745 }
5746
Jim Grosbach8b31f952012-01-23 19:39:08 +00005747 case ARM::VLD1LNdAsm_8:
5748 case ARM::VLD1LNdAsm_16:
5749 case ARM::VLD1LNdAsm_32: {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005750 MCInst TmpInst;
5751 // Shuffle the operands around so the lane index operand is in the
5752 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005753 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005754 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach7636bf62011-12-02 00:35:16 +00005755 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5756 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5757 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5758 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5759 TmpInst.addOperand(Inst.getOperand(1)); // lane
5760 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5761 TmpInst.addOperand(Inst.getOperand(5));
5762 Inst = TmpInst;
5763 return true;
5764 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005765
Jim Grosbach8b31f952012-01-23 19:39:08 +00005766 case ARM::VLD2LNdAsm_8:
5767 case ARM::VLD2LNdAsm_16:
5768 case ARM::VLD2LNdAsm_32:
5769 case ARM::VLD2LNqAsm_16:
5770 case ARM::VLD2LNqAsm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005771 MCInst TmpInst;
5772 // Shuffle the operands around so the lane index operand is in the
5773 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005774 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005775 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005776 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005777 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5778 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005779 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5780 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5781 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005782 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5783 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005784 TmpInst.addOperand(Inst.getOperand(1)); // lane
5785 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5786 TmpInst.addOperand(Inst.getOperand(5));
5787 Inst = TmpInst;
5788 return true;
5789 }
Jim Grosbach3a678af2012-01-23 21:53:26 +00005790
5791 case ARM::VLD3LNdAsm_8:
5792 case ARM::VLD3LNdAsm_16:
5793 case ARM::VLD3LNdAsm_32:
5794 case ARM::VLD3LNqAsm_16:
5795 case ARM::VLD3LNqAsm_32: {
5796 MCInst TmpInst;
5797 // Shuffle the operands around so the lane index operand is in the
5798 // right place.
5799 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005800 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005801 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5802 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5803 Spacing));
5804 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005805 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005806 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5807 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5808 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5809 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5810 Spacing));
5811 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005812 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005813 TmpInst.addOperand(Inst.getOperand(1)); // lane
5814 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5815 TmpInst.addOperand(Inst.getOperand(5));
5816 Inst = TmpInst;
5817 return true;
5818 }
5819
Jim Grosbachc387fc62012-01-23 23:20:46 +00005820 // VLD3 multiple 3-element structure instructions.
5821 case ARM::VLD3dAsm_8:
5822 case ARM::VLD3dAsm_16:
5823 case ARM::VLD3dAsm_32:
5824 case ARM::VLD3qAsm_8:
5825 case ARM::VLD3qAsm_16:
5826 case ARM::VLD3qAsm_32: {
5827 MCInst TmpInst;
5828 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005829 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00005830 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5831 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5832 Spacing));
5833 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5834 Spacing * 2));
5835 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5836 TmpInst.addOperand(Inst.getOperand(2)); // alignment
5837 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5838 TmpInst.addOperand(Inst.getOperand(4));
5839 Inst = TmpInst;
5840 return true;
5841 }
5842
5843 case ARM::VLD3dWB_fixed_Asm_8:
5844 case ARM::VLD3dWB_fixed_Asm_16:
5845 case ARM::VLD3dWB_fixed_Asm_32:
5846 case ARM::VLD3qWB_fixed_Asm_8:
5847 case ARM::VLD3qWB_fixed_Asm_16:
5848 case ARM::VLD3qWB_fixed_Asm_32: {
5849 MCInst TmpInst;
5850 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005851 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00005852 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5853 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5854 Spacing));
5855 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5856 Spacing * 2));
5857 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5858 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
5859 TmpInst.addOperand(Inst.getOperand(2)); // alignment
5860 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5861 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5862 TmpInst.addOperand(Inst.getOperand(4));
5863 Inst = TmpInst;
5864 return true;
5865 }
5866
5867 case ARM::VLD3dWB_register_Asm_8:
5868 case ARM::VLD3dWB_register_Asm_16:
5869 case ARM::VLD3dWB_register_Asm_32:
5870 case ARM::VLD3qWB_register_Asm_8:
5871 case ARM::VLD3qWB_register_Asm_16:
5872 case ARM::VLD3qWB_register_Asm_32: {
5873 MCInst TmpInst;
5874 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005875 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00005876 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5877 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5878 Spacing));
5879 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5880 Spacing * 2));
5881 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5882 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
5883 TmpInst.addOperand(Inst.getOperand(2)); // alignment
5884 TmpInst.addOperand(Inst.getOperand(3)); // Rm
5885 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5886 TmpInst.addOperand(Inst.getOperand(5));
5887 Inst = TmpInst;
5888 return true;
5889 }
5890
Jim Grosbach8abe7e32012-01-24 00:43:17 +00005891 // VLD4 multiple 3-element structure instructions.
5892 case ARM::VLD4dAsm_8:
5893 case ARM::VLD4dAsm_16:
5894 case ARM::VLD4dAsm_32:
5895 case ARM::VLD4qAsm_8:
5896 case ARM::VLD4qAsm_16:
5897 case ARM::VLD4qAsm_32: {
5898 MCInst TmpInst;
5899 unsigned Spacing;
5900 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
5901 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5902 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5903 Spacing));
5904 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5905 Spacing * 2));
5906 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5907 Spacing * 3));
5908 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5909 TmpInst.addOperand(Inst.getOperand(2)); // alignment
5910 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5911 TmpInst.addOperand(Inst.getOperand(4));
5912 Inst = TmpInst;
5913 return true;
5914 }
5915
5916 case ARM::VLD4dWB_fixed_Asm_8:
5917 case ARM::VLD4dWB_fixed_Asm_16:
5918 case ARM::VLD4dWB_fixed_Asm_32:
5919 case ARM::VLD4qWB_fixed_Asm_8:
5920 case ARM::VLD4qWB_fixed_Asm_16:
5921 case ARM::VLD4qWB_fixed_Asm_32: {
5922 MCInst TmpInst;
5923 unsigned Spacing;
5924 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
5925 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5926 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5927 Spacing));
5928 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5929 Spacing * 2));
5930 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5931 Spacing * 3));
5932 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5933 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
5934 TmpInst.addOperand(Inst.getOperand(2)); // alignment
5935 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5936 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5937 TmpInst.addOperand(Inst.getOperand(4));
5938 Inst = TmpInst;
5939 return true;
5940 }
5941
5942 case ARM::VLD4dWB_register_Asm_8:
5943 case ARM::VLD4dWB_register_Asm_16:
5944 case ARM::VLD4dWB_register_Asm_32:
5945 case ARM::VLD4qWB_register_Asm_8:
5946 case ARM::VLD4qWB_register_Asm_16:
5947 case ARM::VLD4qWB_register_Asm_32: {
5948 MCInst TmpInst;
5949 unsigned Spacing;
5950 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
5951 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5952 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5953 Spacing));
5954 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5955 Spacing * 2));
5956 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5957 Spacing * 3));
5958 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5959 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
5960 TmpInst.addOperand(Inst.getOperand(2)); // alignment
5961 TmpInst.addOperand(Inst.getOperand(3)); // Rm
5962 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5963 TmpInst.addOperand(Inst.getOperand(5));
5964 Inst = TmpInst;
5965 return true;
5966 }
5967
Jim Grosbachd7433e22012-01-23 23:45:44 +00005968 // VST3 multiple 3-element structure instructions.
5969 case ARM::VST3dAsm_8:
5970 case ARM::VST3dAsm_16:
5971 case ARM::VST3dAsm_32:
5972 case ARM::VST3qAsm_8:
5973 case ARM::VST3qAsm_16:
5974 case ARM::VST3qAsm_32: {
5975 MCInst TmpInst;
5976 unsigned Spacing;
5977 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5978 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5979 TmpInst.addOperand(Inst.getOperand(2)); // alignment
5980 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5981 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5982 Spacing));
5983 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5984 Spacing * 2));
5985 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5986 TmpInst.addOperand(Inst.getOperand(4));
5987 Inst = TmpInst;
5988 return true;
5989 }
5990
5991 case ARM::VST3dWB_fixed_Asm_8:
5992 case ARM::VST3dWB_fixed_Asm_16:
5993 case ARM::VST3dWB_fixed_Asm_32:
5994 case ARM::VST3qWB_fixed_Asm_8:
5995 case ARM::VST3qWB_fixed_Asm_16:
5996 case ARM::VST3qWB_fixed_Asm_32: {
5997 MCInst TmpInst;
5998 unsigned Spacing;
5999 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6000 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6001 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6002 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6003 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6004 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6005 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6006 Spacing));
6007 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6008 Spacing * 2));
6009 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6010 TmpInst.addOperand(Inst.getOperand(4));
6011 Inst = TmpInst;
6012 return true;
6013 }
6014
6015 case ARM::VST3dWB_register_Asm_8:
6016 case ARM::VST3dWB_register_Asm_16:
6017 case ARM::VST3dWB_register_Asm_32:
6018 case ARM::VST3qWB_register_Asm_8:
6019 case ARM::VST3qWB_register_Asm_16:
6020 case ARM::VST3qWB_register_Asm_32: {
6021 MCInst TmpInst;
6022 unsigned Spacing;
6023 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6024 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6025 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6026 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6027 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6028 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6029 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6030 Spacing));
6031 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6032 Spacing * 2));
6033 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6034 TmpInst.addOperand(Inst.getOperand(5));
6035 Inst = TmpInst;
6036 return true;
6037 }
6038
Jim Grosbach539aab72012-01-24 00:58:13 +00006039 // VST4 multiple 3-element structure instructions.
6040 case ARM::VST4dAsm_8:
6041 case ARM::VST4dAsm_16:
6042 case ARM::VST4dAsm_32:
6043 case ARM::VST4qAsm_8:
6044 case ARM::VST4qAsm_16:
6045 case ARM::VST4qAsm_32: {
6046 MCInst TmpInst;
6047 unsigned Spacing;
6048 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6049 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6050 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6051 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6052 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6053 Spacing));
6054 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6055 Spacing * 2));
6056 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6057 Spacing * 3));
6058 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6059 TmpInst.addOperand(Inst.getOperand(4));
6060 Inst = TmpInst;
6061 return true;
6062 }
6063
6064 case ARM::VST4dWB_fixed_Asm_8:
6065 case ARM::VST4dWB_fixed_Asm_16:
6066 case ARM::VST4dWB_fixed_Asm_32:
6067 case ARM::VST4qWB_fixed_Asm_8:
6068 case ARM::VST4qWB_fixed_Asm_16:
6069 case ARM::VST4qWB_fixed_Asm_32: {
6070 MCInst TmpInst;
6071 unsigned Spacing;
6072 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6073 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6074 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6075 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6076 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6077 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6078 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6079 Spacing));
6080 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6081 Spacing * 2));
6082 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6083 Spacing * 3));
6084 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6085 TmpInst.addOperand(Inst.getOperand(4));
6086 Inst = TmpInst;
6087 return true;
6088 }
6089
6090 case ARM::VST4dWB_register_Asm_8:
6091 case ARM::VST4dWB_register_Asm_16:
6092 case ARM::VST4dWB_register_Asm_32:
6093 case ARM::VST4qWB_register_Asm_8:
6094 case ARM::VST4qWB_register_Asm_16:
6095 case ARM::VST4qWB_register_Asm_32: {
6096 MCInst TmpInst;
6097 unsigned Spacing;
6098 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6099 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6100 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6101 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6102 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6103 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6104 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6105 Spacing));
6106 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6107 Spacing * 2));
6108 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6109 Spacing * 3));
6110 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6111 TmpInst.addOperand(Inst.getOperand(5));
6112 Inst = TmpInst;
6113 return true;
6114 }
6115
Jim Grosbach863d2af2011-12-13 22:45:11 +00006116 // Handle the Thumb2 mode MOV complex aliases.
Jim Grosbach2cc5cda2011-12-21 20:54:00 +00006117 case ARM::t2MOVsr:
6118 case ARM::t2MOVSsr: {
6119 // Which instruction to expand to depends on the CCOut operand and
6120 // whether we're in an IT block if the register operands are low
6121 // registers.
6122 bool isNarrow = false;
6123 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6124 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6125 isARMLowRegister(Inst.getOperand(2).getReg()) &&
6126 Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
6127 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsr))
6128 isNarrow = true;
6129 MCInst TmpInst;
6130 unsigned newOpc;
6131 switch(ARM_AM::getSORegShOp(Inst.getOperand(3).getImm())) {
6132 default: llvm_unreachable("unexpected opcode!");
6133 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRrr : ARM::t2ASRrr; break;
6134 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRrr : ARM::t2LSRrr; break;
6135 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLrr : ARM::t2LSLrr; break;
6136 case ARM_AM::ror: newOpc = isNarrow ? ARM::tROR : ARM::t2RORrr; break;
6137 }
6138 TmpInst.setOpcode(newOpc);
6139 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6140 if (isNarrow)
6141 TmpInst.addOperand(MCOperand::CreateReg(
6142 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6143 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6144 TmpInst.addOperand(Inst.getOperand(2)); // Rm
6145 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6146 TmpInst.addOperand(Inst.getOperand(5));
6147 if (!isNarrow)
6148 TmpInst.addOperand(MCOperand::CreateReg(
6149 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6150 Inst = TmpInst;
6151 return true;
6152 }
Jim Grosbach863d2af2011-12-13 22:45:11 +00006153 case ARM::t2MOVsi:
6154 case ARM::t2MOVSsi: {
6155 // Which instruction to expand to depends on the CCOut operand and
6156 // whether we're in an IT block if the register operands are low
6157 // registers.
6158 bool isNarrow = false;
6159 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6160 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6161 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
6162 isNarrow = true;
6163 MCInst TmpInst;
6164 unsigned newOpc;
6165 switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
6166 default: llvm_unreachable("unexpected opcode!");
6167 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
6168 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
6169 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
6170 case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
Jim Grosbach520dc782011-12-21 21:04:19 +00006171 case ARM_AM::rrx: isNarrow = false; newOpc = ARM::t2RRX; break;
Jim Grosbach863d2af2011-12-13 22:45:11 +00006172 }
6173 unsigned Ammount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
6174 if (Ammount == 32) Ammount = 0;
6175 TmpInst.setOpcode(newOpc);
6176 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6177 if (isNarrow)
6178 TmpInst.addOperand(MCOperand::CreateReg(
6179 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6180 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbach520dc782011-12-21 21:04:19 +00006181 if (newOpc != ARM::t2RRX)
6182 TmpInst.addOperand(MCOperand::CreateImm(Ammount));
Jim Grosbach863d2af2011-12-13 22:45:11 +00006183 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6184 TmpInst.addOperand(Inst.getOperand(4));
6185 if (!isNarrow)
6186 TmpInst.addOperand(MCOperand::CreateReg(
6187 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6188 Inst = TmpInst;
6189 return true;
6190 }
6191 // Handle the ARM mode MOV complex aliases.
Jim Grosbach23f22072011-11-16 18:31:45 +00006192 case ARM::ASRr:
6193 case ARM::LSRr:
6194 case ARM::LSLr:
6195 case ARM::RORr: {
6196 ARM_AM::ShiftOpc ShiftTy;
6197 switch(Inst.getOpcode()) {
6198 default: llvm_unreachable("unexpected opcode!");
6199 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
6200 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
6201 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
6202 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
6203 }
Jim Grosbach23f22072011-11-16 18:31:45 +00006204 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
6205 MCInst TmpInst;
6206 TmpInst.setOpcode(ARM::MOVsr);
6207 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6208 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6209 TmpInst.addOperand(Inst.getOperand(2)); // Rm
6210 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6211 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6212 TmpInst.addOperand(Inst.getOperand(4));
6213 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6214 Inst = TmpInst;
6215 return true;
6216 }
Jim Grosbachee10ff82011-11-10 19:18:01 +00006217 case ARM::ASRi:
6218 case ARM::LSRi:
6219 case ARM::LSLi:
6220 case ARM::RORi: {
6221 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachee10ff82011-11-10 19:18:01 +00006222 switch(Inst.getOpcode()) {
6223 default: llvm_unreachable("unexpected opcode!");
6224 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
6225 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
6226 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
6227 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
6228 }
6229 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach48b368b2011-11-16 19:05:59 +00006230 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachee10ff82011-11-10 19:18:01 +00006231 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
6232 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach71810ab2011-11-10 16:44:55 +00006233 MCInst TmpInst;
Jim Grosbachee10ff82011-11-10 19:18:01 +00006234 TmpInst.setOpcode(Opc);
Jim Grosbach71810ab2011-11-10 16:44:55 +00006235 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6236 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachee10ff82011-11-10 19:18:01 +00006237 if (Opc == ARM::MOVsi)
6238 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach71810ab2011-11-10 16:44:55 +00006239 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6240 TmpInst.addOperand(Inst.getOperand(4));
6241 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6242 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006243 return true;
Jim Grosbach71810ab2011-11-10 16:44:55 +00006244 }
Jim Grosbach48b368b2011-11-16 19:05:59 +00006245 case ARM::RRXi: {
6246 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
6247 MCInst TmpInst;
6248 TmpInst.setOpcode(ARM::MOVsi);
6249 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6250 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6251 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6252 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6253 TmpInst.addOperand(Inst.getOperand(3));
6254 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
6255 Inst = TmpInst;
6256 return true;
6257 }
Jim Grosbach0352b462011-11-10 23:58:34 +00006258 case ARM::t2LDMIA_UPD: {
6259 // If this is a load of a single register, then we should use
6260 // a post-indexed LDR instruction instead, per the ARM ARM.
6261 if (Inst.getNumOperands() != 5)
6262 return false;
6263 MCInst TmpInst;
6264 TmpInst.setOpcode(ARM::t2LDR_POST);
6265 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6266 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6267 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6268 TmpInst.addOperand(MCOperand::CreateImm(4));
6269 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6270 TmpInst.addOperand(Inst.getOperand(3));
6271 Inst = TmpInst;
6272 return true;
6273 }
6274 case ARM::t2STMDB_UPD: {
6275 // If this is a store of a single register, then we should use
6276 // a pre-indexed STR instruction instead, per the ARM ARM.
6277 if (Inst.getNumOperands() != 5)
6278 return false;
6279 MCInst TmpInst;
6280 TmpInst.setOpcode(ARM::t2STR_PRE);
6281 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6282 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6283 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6284 TmpInst.addOperand(MCOperand::CreateImm(-4));
6285 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6286 TmpInst.addOperand(Inst.getOperand(3));
6287 Inst = TmpInst;
6288 return true;
6289 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00006290 case ARM::LDMIA_UPD:
6291 // If this is a load of a single register via a 'pop', then we should use
6292 // a post-indexed LDR instruction instead, per the ARM ARM.
6293 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
6294 Inst.getNumOperands() == 5) {
6295 MCInst TmpInst;
6296 TmpInst.setOpcode(ARM::LDR_POST_IMM);
6297 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6298 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6299 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6300 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
6301 TmpInst.addOperand(MCOperand::CreateImm(4));
6302 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6303 TmpInst.addOperand(Inst.getOperand(3));
6304 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006305 return true;
Jim Grosbachf8fce712011-08-11 17:35:48 +00006306 }
6307 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00006308 case ARM::STMDB_UPD:
6309 // If this is a store of a single register via a 'push', then we should use
6310 // a pre-indexed STR instruction instead, per the ARM ARM.
6311 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
6312 Inst.getNumOperands() == 5) {
6313 MCInst TmpInst;
6314 TmpInst.setOpcode(ARM::STR_PRE_IMM);
6315 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6316 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6317 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
6318 TmpInst.addOperand(MCOperand::CreateImm(-4));
6319 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6320 TmpInst.addOperand(Inst.getOperand(3));
6321 Inst = TmpInst;
6322 }
6323 break;
Jim Grosbachda847862011-12-05 21:06:26 +00006324 case ARM::t2ADDri12:
6325 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
6326 // mnemonic was used (not "addw"), encoding T3 is preferred.
6327 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
6328 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
6329 break;
6330 Inst.setOpcode(ARM::t2ADDri);
6331 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
6332 break;
6333 case ARM::t2SUBri12:
6334 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
6335 // mnemonic was used (not "subw"), encoding T3 is preferred.
6336 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
6337 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
6338 break;
6339 Inst.setOpcode(ARM::t2SUBri);
6340 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
6341 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006342 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00006343 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6344 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6345 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6346 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00006347 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006348 Inst.setOpcode(ARM::tADDi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006349 return true;
6350 }
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006351 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00006352 case ARM::tSUBi8:
6353 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6354 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6355 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6356 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00006357 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachf67e8552011-09-16 22:58:42 +00006358 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006359 return true;
6360 }
Jim Grosbachf67e8552011-09-16 22:58:42 +00006361 break;
Jim Grosbach927b9df2011-12-05 22:16:39 +00006362 case ARM::t2ADDrr: {
6363 // If the destination and first source operand are the same, and
6364 // there's no setting of the flags, use encoding T2 instead of T3.
6365 // Note that this is only for ADD, not SUB. This mirrors the system
6366 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
6367 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
6368 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbach713c7022011-12-05 22:27:04 +00006369 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6370 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbach927b9df2011-12-05 22:16:39 +00006371 break;
6372 MCInst TmpInst;
6373 TmpInst.setOpcode(ARM::tADDhirr);
6374 TmpInst.addOperand(Inst.getOperand(0));
6375 TmpInst.addOperand(Inst.getOperand(0));
6376 TmpInst.addOperand(Inst.getOperand(2));
6377 TmpInst.addOperand(Inst.getOperand(3));
6378 TmpInst.addOperand(Inst.getOperand(4));
6379 Inst = TmpInst;
6380 return true;
6381 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006382 case ARM::tB:
6383 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006384 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006385 Inst.setOpcode(ARM::tBcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006386 return true;
6387 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006388 break;
6389 case ARM::t2B:
6390 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006391 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006392 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006393 return true;
6394 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006395 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00006396 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00006397 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006398 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbachc0755102011-08-31 21:17:31 +00006399 Inst.setOpcode(ARM::t2B);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006400 return true;
6401 }
Jim Grosbachc0755102011-08-31 21:17:31 +00006402 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00006403 case ARM::tBcc:
6404 // If the conditional is AL, we really want tB.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006405 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbach395b4532011-08-17 22:57:40 +00006406 Inst.setOpcode(ARM::tB);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006407 return true;
6408 }
Jim Grosbach3ce23d32011-08-18 16:08:39 +00006409 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00006410 case ARM::tLDMIA: {
6411 // If the register list contains any high registers, or if the writeback
6412 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
6413 // instead if we're in Thumb2. Otherwise, this should have generated
6414 // an error in validateInstruction().
6415 unsigned Rn = Inst.getOperand(0).getReg();
6416 bool hasWritebackToken =
6417 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6418 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
6419 bool listContainsBase;
6420 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
6421 (!listContainsBase && !hasWritebackToken) ||
6422 (listContainsBase && hasWritebackToken)) {
6423 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6424 assert (isThumbTwo());
6425 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
6426 // If we're switching to the updating version, we need to insert
6427 // the writeback tied operand.
6428 if (hasWritebackToken)
6429 Inst.insert(Inst.begin(),
6430 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006431 return true;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00006432 }
6433 break;
6434 }
Jim Grosbach8213c962011-09-16 20:50:13 +00006435 case ARM::tSTMIA_UPD: {
6436 // If the register list contains any high registers, we need to use
6437 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6438 // should have generated an error in validateInstruction().
6439 unsigned Rn = Inst.getOperand(0).getReg();
6440 bool listContainsBase;
6441 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
6442 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6443 assert (isThumbTwo());
6444 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006445 return true;
Jim Grosbach8213c962011-09-16 20:50:13 +00006446 }
6447 break;
6448 }
Jim Grosbach54026372011-11-10 23:17:11 +00006449 case ARM::tPOP: {
6450 bool listContainsBase;
6451 // If the register list contains any high registers, we need to use
6452 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6453 // should have generated an error in validateInstruction().
6454 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00006455 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00006456 assert (isThumbTwo());
6457 Inst.setOpcode(ARM::t2LDMIA_UPD);
6458 // Add the base register and writeback operands.
6459 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6460 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006461 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00006462 }
6463 case ARM::tPUSH: {
6464 bool listContainsBase;
6465 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00006466 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00006467 assert (isThumbTwo());
6468 Inst.setOpcode(ARM::t2STMDB_UPD);
6469 // Add the base register and writeback operands.
6470 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6471 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006472 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00006473 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006474 case ARM::t2MOVi: {
6475 // If we can use the 16-bit encoding and the user didn't explicitly
6476 // request the 32-bit variant, transform it here.
6477 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6478 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00006479 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
6480 Inst.getOperand(4).getReg() == ARM::CPSR) ||
6481 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006482 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6483 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6484 // The operands aren't in the same order for tMOVi8...
6485 MCInst TmpInst;
6486 TmpInst.setOpcode(ARM::tMOVi8);
6487 TmpInst.addOperand(Inst.getOperand(0));
6488 TmpInst.addOperand(Inst.getOperand(4));
6489 TmpInst.addOperand(Inst.getOperand(1));
6490 TmpInst.addOperand(Inst.getOperand(2));
6491 TmpInst.addOperand(Inst.getOperand(3));
6492 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006493 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006494 }
6495 break;
6496 }
6497 case ARM::t2MOVr: {
6498 // If we can use the 16-bit encoding and the user didn't explicitly
6499 // request the 32-bit variant, transform it here.
6500 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6501 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6502 Inst.getOperand(2).getImm() == ARMCC::AL &&
6503 Inst.getOperand(4).getReg() == ARM::CPSR &&
6504 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6505 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6506 // The operands aren't the same for tMOV[S]r... (no cc_out)
6507 MCInst TmpInst;
6508 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
6509 TmpInst.addOperand(Inst.getOperand(0));
6510 TmpInst.addOperand(Inst.getOperand(1));
6511 TmpInst.addOperand(Inst.getOperand(2));
6512 TmpInst.addOperand(Inst.getOperand(3));
6513 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006514 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006515 }
6516 break;
6517 }
Jim Grosbach326efe52011-09-19 20:29:33 +00006518 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00006519 case ARM::t2SXTB:
6520 case ARM::t2UXTH:
6521 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00006522 // If we can use the 16-bit encoding and the user didn't explicitly
6523 // request the 32-bit variant, transform it here.
6524 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6525 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6526 Inst.getOperand(2).getImm() == 0 &&
6527 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6528 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00006529 unsigned NewOpc;
6530 switch (Inst.getOpcode()) {
6531 default: llvm_unreachable("Illegal opcode!");
6532 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
6533 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
6534 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
6535 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
6536 }
Jim Grosbach326efe52011-09-19 20:29:33 +00006537 // The operands aren't the same for thumb1 (no rotate operand).
6538 MCInst TmpInst;
6539 TmpInst.setOpcode(NewOpc);
6540 TmpInst.addOperand(Inst.getOperand(0));
6541 TmpInst.addOperand(Inst.getOperand(1));
6542 TmpInst.addOperand(Inst.getOperand(3));
6543 TmpInst.addOperand(Inst.getOperand(4));
6544 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006545 return true;
Jim Grosbach326efe52011-09-19 20:29:33 +00006546 }
6547 break;
6548 }
Jim Grosbach04b5d932011-12-20 00:59:38 +00006549 case ARM::MOVsi: {
6550 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm());
6551 if (SOpc == ARM_AM::rrx) return false;
6552 if (ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()) == 0) {
6553 // Shifting by zero is accepted as a vanilla 'MOVr'
6554 MCInst TmpInst;
6555 TmpInst.setOpcode(ARM::MOVr);
6556 TmpInst.addOperand(Inst.getOperand(0));
6557 TmpInst.addOperand(Inst.getOperand(1));
6558 TmpInst.addOperand(Inst.getOperand(3));
6559 TmpInst.addOperand(Inst.getOperand(4));
6560 TmpInst.addOperand(Inst.getOperand(5));
6561 Inst = TmpInst;
6562 return true;
6563 }
6564 return false;
6565 }
Jim Grosbach8d9550b2011-12-22 18:04:04 +00006566 case ARM::ANDrsi:
6567 case ARM::ORRrsi:
6568 case ARM::EORrsi:
6569 case ARM::BICrsi:
6570 case ARM::SUBrsi:
6571 case ARM::ADDrsi: {
6572 unsigned newOpc;
6573 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(3).getImm());
6574 if (SOpc == ARM_AM::rrx) return false;
6575 switch (Inst.getOpcode()) {
Matt Beaumont-Gay19055cc2012-01-03 19:03:59 +00006576 default: assert(0 && "unexpected opcode!");
Jim Grosbach8d9550b2011-12-22 18:04:04 +00006577 case ARM::ANDrsi: newOpc = ARM::ANDrr; break;
6578 case ARM::ORRrsi: newOpc = ARM::ORRrr; break;
6579 case ARM::EORrsi: newOpc = ARM::EORrr; break;
6580 case ARM::BICrsi: newOpc = ARM::BICrr; break;
6581 case ARM::SUBrsi: newOpc = ARM::SUBrr; break;
6582 case ARM::ADDrsi: newOpc = ARM::ADDrr; break;
6583 }
6584 // If the shift is by zero, use the non-shifted instruction definition.
6585 if (ARM_AM::getSORegOffset(Inst.getOperand(3).getImm()) == 0) {
6586 MCInst TmpInst;
6587 TmpInst.setOpcode(newOpc);
6588 TmpInst.addOperand(Inst.getOperand(0));
6589 TmpInst.addOperand(Inst.getOperand(1));
6590 TmpInst.addOperand(Inst.getOperand(2));
6591 TmpInst.addOperand(Inst.getOperand(4));
6592 TmpInst.addOperand(Inst.getOperand(5));
6593 TmpInst.addOperand(Inst.getOperand(6));
6594 Inst = TmpInst;
6595 return true;
6596 }
6597 return false;
6598 }
Jim Grosbach89df9962011-08-26 21:43:41 +00006599 case ARM::t2IT: {
6600 // The mask bits for all but the first condition are represented as
6601 // the low bit of the condition code value implies 't'. We currently
6602 // always have 1 implies 't', so XOR toggle the bits if the low bit
6603 // of the condition code is zero. The encoding also expects the low
6604 // bit of the condition to be encoded as bit 4 of the mask operand,
6605 // so mask that in if needed
6606 MCOperand &MO = Inst.getOperand(1);
6607 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006608 unsigned OrigMask = Mask;
6609 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00006610 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00006611 assert(Mask && TZ <= 3 && "illegal IT mask value!");
6612 for (unsigned i = 3; i != TZ; --i)
6613 Mask ^= 1 << i;
6614 } else
6615 Mask |= 0x10;
6616 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006617
6618 // Set up the IT block state according to the IT instruction we just
6619 // matched.
6620 assert(!inITBlock() && "nested IT blocks?!");
6621 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
6622 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
6623 ITState.CurPosition = 0;
6624 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00006625 break;
6626 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00006627 }
Jim Grosbach83ec8772011-11-10 23:42:14 +00006628 return false;
Jim Grosbachf8fce712011-08-11 17:35:48 +00006629}
6630
Jim Grosbach47a0d522011-08-16 20:45:50 +00006631unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
6632 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
6633 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00006634 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00006635 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00006636 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
6637 assert(MCID.hasOptionalDef() &&
6638 "optionally flag setting instruction missing optional def operand");
6639 assert(MCID.NumOperands == Inst.getNumOperands() &&
6640 "operand count mismatch!");
6641 // Find the optional-def operand (cc_out).
6642 unsigned OpNo;
6643 for (OpNo = 0;
6644 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
6645 ++OpNo)
6646 ;
6647 // If we're parsing Thumb1, reject it completely.
6648 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
6649 return Match_MnemonicFail;
6650 // If we're parsing Thumb2, which form is legal depends on whether we're
6651 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006652 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
6653 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00006654 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006655 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
6656 inITBlock())
6657 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00006658 }
Jim Grosbach194bd892011-08-16 22:20:01 +00006659 // Some high-register supporting Thumb1 encodings only allow both registers
6660 // to be from r0-r7 when in Thumb2.
6661 else if (Opc == ARM::tADDhirr && isThumbOne() &&
6662 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6663 isARMLowRegister(Inst.getOperand(2).getReg()))
6664 return Match_RequiresThumb2;
6665 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00006666 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00006667 isARMLowRegister(Inst.getOperand(0).getReg()) &&
6668 isARMLowRegister(Inst.getOperand(1).getReg()))
6669 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00006670 return Match_Success;
6671}
6672
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006673bool ARMAsmParser::
6674MatchAndEmitInstruction(SMLoc IDLoc,
6675 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
6676 MCStreamer &Out) {
6677 MCInst Inst;
6678 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00006679 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00006680 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00006681 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00006682 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00006683 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00006684 // Context sensitive operand constraints aren't handled by the matcher,
6685 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00006686 if (validateInstruction(Inst, Operands)) {
6687 // Still progress the IT block, otherwise one wrong condition causes
6688 // nasty cascading errors.
6689 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00006690 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00006691 }
Jim Grosbach189610f2011-07-26 18:25:39 +00006692
Jim Grosbachf8fce712011-08-11 17:35:48 +00006693 // Some instructions need post-processing to, for example, tweak which
Jim Grosbach83ec8772011-11-10 23:42:14 +00006694 // encoding is selected. Loop on it while changes happen so the
6695 // individual transformations can chain off each other. E.g.,
6696 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
6697 while (processInstruction(Inst, Operands))
6698 ;
Jim Grosbachf8fce712011-08-11 17:35:48 +00006699
Jim Grosbacha1109882011-09-02 23:22:08 +00006700 // Only move forward at the very end so that everything in validate
6701 // and process gets a consistent answer about whether we're in an IT
6702 // block.
6703 forwardITPosition();
6704
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006705 Out.EmitInstruction(Inst);
6706 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00006707 case Match_MissingFeature:
6708 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
6709 return true;
6710 case Match_InvalidOperand: {
6711 SMLoc ErrorLoc = IDLoc;
6712 if (ErrorInfo != ~0U) {
6713 if (ErrorInfo >= Operands.size())
6714 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00006715
Chris Lattnere73d4f82010-10-28 21:41:58 +00006716 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
6717 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
6718 }
Jim Grosbach16c74252010-10-29 14:46:02 +00006719
Chris Lattnere73d4f82010-10-28 21:41:58 +00006720 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006721 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00006722 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00006723 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00006724 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00006725 // The converter function will have already emited a diagnostic.
6726 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006727 case Match_RequiresNotITBlock:
6728 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00006729 case Match_RequiresITBlock:
6730 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00006731 case Match_RequiresV6:
6732 return Error(IDLoc, "instruction variant requires ARMv6 or later");
6733 case Match_RequiresThumb2:
6734 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00006735 }
Jim Grosbach16c74252010-10-29 14:46:02 +00006736
Eric Christopherc223e2b2010-10-29 09:26:59 +00006737 llvm_unreachable("Implement any new match types added!");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006738}
6739
Jim Grosbach1355cf12011-07-26 17:10:22 +00006740/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006741bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
6742 StringRef IDVal = DirectiveID.getIdentifier();
6743 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006744 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006745 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006746 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach9a70df92011-12-07 18:04:19 +00006747 else if (IDVal == ".arm")
6748 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006749 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006750 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006751 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006752 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006753 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006754 return parseDirectiveSyntax(DirectiveID.getLoc());
Jim Grosbacha39cda72011-12-14 02:16:11 +00006755 else if (IDVal == ".unreq")
6756 return parseDirectiveUnreq(DirectiveID.getLoc());
Jason W Kimd7c9e082011-12-20 17:38:12 +00006757 else if (IDVal == ".arch")
6758 return parseDirectiveArch(DirectiveID.getLoc());
6759 else if (IDVal == ".eabi_attribute")
6760 return parseDirectiveEabiAttr(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006761 return true;
6762}
6763
Jim Grosbach1355cf12011-07-26 17:10:22 +00006764/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006765/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00006766bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006767 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6768 for (;;) {
6769 const MCExpr *Value;
6770 if (getParser().ParseExpression(Value))
6771 return true;
6772
Chris Lattneraaec2052010-01-19 19:46:13 +00006773 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006774
6775 if (getLexer().is(AsmToken::EndOfStatement))
6776 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00006777
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006778 // FIXME: Improve diagnostic.
6779 if (getLexer().isNot(AsmToken::Comma))
6780 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006781 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006782 }
6783 }
6784
Sean Callananb9a25b72010-01-19 20:27:46 +00006785 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006786 return false;
6787}
6788
Jim Grosbach1355cf12011-07-26 17:10:22 +00006789/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00006790/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00006791bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00006792 if (getLexer().isNot(AsmToken::EndOfStatement))
6793 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006794 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006795
Jim Grosbach9a70df92011-12-07 18:04:19 +00006796 if (!isThumb())
6797 SwitchMode();
6798 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
6799 return false;
6800}
6801
6802/// parseDirectiveARM
6803/// ::= .arm
6804bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
6805 if (getLexer().isNot(AsmToken::EndOfStatement))
6806 return Error(L, "unexpected token in directive");
6807 Parser.Lex();
6808
6809 if (isThumb())
6810 SwitchMode();
6811 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby515d5092009-10-15 20:48:48 +00006812 return false;
6813}
6814
Jim Grosbach1355cf12011-07-26 17:10:22 +00006815/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00006816/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00006817bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00006818 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
6819 bool isMachO = MAI.hasSubsectionsViaSymbols();
6820 StringRef Name;
Jim Grosbachde4d8392011-12-21 22:30:16 +00006821 bool needFuncName = true;
Rafael Espindola64695402011-05-16 16:17:21 +00006822
Jim Grosbachde4d8392011-12-21 22:30:16 +00006823 // Darwin asm has (optionally) function name after .thumb_func direction
Rafael Espindola64695402011-05-16 16:17:21 +00006824 // ELF doesn't
6825 if (isMachO) {
6826 const AsmToken &Tok = Parser.getTok();
Jim Grosbachde4d8392011-12-21 22:30:16 +00006827 if (Tok.isNot(AsmToken::EndOfStatement)) {
6828 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
6829 return Error(L, "unexpected token in .thumb_func directive");
6830 Name = Tok.getIdentifier();
6831 Parser.Lex(); // Consume the identifier token.
6832 needFuncName = false;
6833 }
Rafael Espindola64695402011-05-16 16:17:21 +00006834 }
6835
Jim Grosbachde4d8392011-12-21 22:30:16 +00006836 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby515d5092009-10-15 20:48:48 +00006837 return Error(L, "unexpected token in directive");
Jim Grosbachde4d8392011-12-21 22:30:16 +00006838
6839 // Eat the end of statement and any blank lines that follow.
6840 while (getLexer().is(AsmToken::EndOfStatement))
6841 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006842
Rafael Espindola64695402011-05-16 16:17:21 +00006843 // FIXME: assuming function name will be the line following .thumb_func
Jim Grosbachde4d8392011-12-21 22:30:16 +00006844 // We really should be checking the next symbol definition even if there's
6845 // stuff in between.
6846 if (needFuncName) {
Jim Grosbachd475f862011-11-10 20:48:53 +00006847 Name = Parser.getTok().getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00006848 }
6849
Jim Grosbach642fc9c2010-11-05 22:33:53 +00006850 // Mark symbol as a thumb symbol.
6851 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
6852 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00006853 return false;
6854}
6855
Jim Grosbach1355cf12011-07-26 17:10:22 +00006856/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00006857/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00006858bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00006859 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00006860 if (Tok.isNot(AsmToken::Identifier))
6861 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00006862 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00006863 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00006864 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00006865 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00006866 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00006867 else
6868 return Error(L, "unrecognized syntax mode in .syntax directive");
6869
6870 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00006871 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006872 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006873
6874 // TODO tell the MC streamer the mode
6875 // getParser().getStreamer().Emit???();
6876 return false;
6877}
6878
Jim Grosbach1355cf12011-07-26 17:10:22 +00006879/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00006880/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00006881bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00006882 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00006883 if (Tok.isNot(AsmToken::Integer))
6884 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00006885 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00006886 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00006887 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00006888 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00006889 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006890 else
6891 return Error(L, "invalid operand to .code directive");
6892
6893 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00006894 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006895 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006896
Evan Cheng32869202011-07-08 22:36:29 +00006897 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00006898 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00006899 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00006900 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00006901 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00006902 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00006903 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00006904 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00006905 }
Jim Grosbach2a301702010-11-05 22:40:53 +00006906
Kevin Enderby515d5092009-10-15 20:48:48 +00006907 return false;
6908}
6909
Jim Grosbacha39cda72011-12-14 02:16:11 +00006910/// parseDirectiveReq
6911/// ::= name .req registername
6912bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
6913 Parser.Lex(); // Eat the '.req' token.
6914 unsigned Reg;
6915 SMLoc SRegLoc, ERegLoc;
6916 if (ParseRegister(Reg, SRegLoc, ERegLoc)) {
6917 Parser.EatToEndOfStatement();
6918 return Error(SRegLoc, "register name expected");
6919 }
6920
6921 // Shouldn't be anything else.
6922 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
6923 Parser.EatToEndOfStatement();
6924 return Error(Parser.getTok().getLoc(),
6925 "unexpected input in .req directive.");
6926 }
6927
6928 Parser.Lex(); // Consume the EndOfStatement
6929
6930 if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg)
6931 return Error(SRegLoc, "redefinition of '" + Name +
6932 "' does not match original.");
6933
6934 return false;
6935}
6936
6937/// parseDirectiveUneq
6938/// ::= .unreq registername
6939bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
6940 if (Parser.getTok().isNot(AsmToken::Identifier)) {
6941 Parser.EatToEndOfStatement();
6942 return Error(L, "unexpected input in .unreq directive.");
6943 }
6944 RegisterReqs.erase(Parser.getTok().getIdentifier());
6945 Parser.Lex(); // Eat the identifier.
6946 return false;
6947}
6948
Jason W Kimd7c9e082011-12-20 17:38:12 +00006949/// parseDirectiveArch
6950/// ::= .arch token
6951bool ARMAsmParser::parseDirectiveArch(SMLoc L) {
6952 return true;
6953}
6954
6955/// parseDirectiveEabiAttr
6956/// ::= .eabi_attribute int, int
6957bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
6958 return true;
6959}
6960
Sean Callanan90b70972010-04-07 20:29:34 +00006961extern "C" void LLVMInitializeARMAsmLexer();
6962
Kevin Enderby9c41fa82009-10-30 22:55:57 +00006963/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006964extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00006965 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
6966 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00006967 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006968}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00006969
Chris Lattner0692ee62010-09-06 19:11:01 +00006970#define GET_REGISTER_MATCHER
6971#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00006972#include "ARMGenAsmMatcher.inc"