blob: 414f9f5b7ffcaf104d7b6212f9c5b3037f73acec [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 Grosbach5e59f7e2012-01-24 23:47:04 +00001135 bool isVecListThreeDAllLanes() const {
1136 if (!isSingleSpacedVectorAllLanes()) return false;
1137 return VectorList.Count == 3;
1138 }
1139
1140 bool isVecListThreeQAllLanes() const {
1141 if (!isDoubleSpacedVectorAllLanes()) return false;
1142 return VectorList.Count == 3;
1143 }
1144
Jim Grosbacha57a36a2012-01-25 00:01:08 +00001145 bool isVecListFourDAllLanes() const {
1146 if (!isSingleSpacedVectorAllLanes()) return false;
1147 return VectorList.Count == 4;
1148 }
1149
1150 bool isVecListFourQAllLanes() const {
1151 if (!isDoubleSpacedVectorAllLanes()) return false;
1152 return VectorList.Count == 4;
1153 }
1154
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001155 bool isSingleSpacedVectorIndexed() const {
1156 return Kind == k_VectorListIndexed && !VectorList.isDoubleSpaced;
1157 }
1158 bool isDoubleSpacedVectorIndexed() const {
1159 return Kind == k_VectorListIndexed && VectorList.isDoubleSpaced;
1160 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00001161 bool isVecListOneDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001162 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach7636bf62011-12-02 00:35:16 +00001163 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1164 }
1165
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001166 bool isVecListOneDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001167 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001168 return VectorList.Count == 1 && VectorList.LaneIndex <= 3;
1169 }
1170
1171 bool isVecListOneDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001172 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001173 return VectorList.Count == 1 && VectorList.LaneIndex <= 1;
1174 }
1175
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001176 bool isVecListTwoDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001177 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001178 return VectorList.Count == 2 && VectorList.LaneIndex <= 7;
1179 }
1180
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001181 bool isVecListTwoDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001182 if (!isSingleSpacedVectorIndexed()) return false;
1183 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1184 }
1185
1186 bool isVecListTwoQWordIndexed() const {
1187 if (!isDoubleSpacedVectorIndexed()) return false;
1188 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1189 }
1190
1191 bool isVecListTwoQHWordIndexed() const {
1192 if (!isDoubleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001193 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1194 }
1195
1196 bool isVecListTwoDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001197 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001198 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1199 }
1200
Jim Grosbach3a678af2012-01-23 21:53:26 +00001201 bool isVecListThreeDByteIndexed() const {
1202 if (!isSingleSpacedVectorIndexed()) return false;
1203 return VectorList.Count == 3 && VectorList.LaneIndex <= 7;
1204 }
1205
1206 bool isVecListThreeDHWordIndexed() const {
1207 if (!isSingleSpacedVectorIndexed()) return false;
1208 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1209 }
1210
1211 bool isVecListThreeQWordIndexed() const {
1212 if (!isDoubleSpacedVectorIndexed()) return false;
1213 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1214 }
1215
1216 bool isVecListThreeQHWordIndexed() const {
1217 if (!isDoubleSpacedVectorIndexed()) return false;
1218 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1219 }
1220
1221 bool isVecListThreeDWordIndexed() const {
1222 if (!isSingleSpacedVectorIndexed()) return false;
1223 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1224 }
1225
Jim Grosbache983a132012-01-24 18:37:25 +00001226 bool isVecListFourDByteIndexed() const {
1227 if (!isSingleSpacedVectorIndexed()) return false;
1228 return VectorList.Count == 4 && VectorList.LaneIndex <= 7;
1229 }
1230
1231 bool isVecListFourDHWordIndexed() const {
1232 if (!isSingleSpacedVectorIndexed()) return false;
1233 return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1234 }
1235
1236 bool isVecListFourQWordIndexed() const {
1237 if (!isDoubleSpacedVectorIndexed()) return false;
1238 return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1239 }
1240
1241 bool isVecListFourQHWordIndexed() const {
1242 if (!isDoubleSpacedVectorIndexed()) return false;
1243 return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1244 }
1245
1246 bool isVecListFourDWordIndexed() const {
1247 if (!isSingleSpacedVectorIndexed()) return false;
1248 return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1249 }
1250
Jim Grosbach460a9052011-10-07 23:56:00 +00001251 bool isVectorIndex8() const {
1252 if (Kind != k_VectorIndex) return false;
1253 return VectorIndex.Val < 8;
1254 }
1255 bool isVectorIndex16() const {
1256 if (Kind != k_VectorIndex) return false;
1257 return VectorIndex.Val < 4;
1258 }
1259 bool isVectorIndex32() const {
1260 if (Kind != k_VectorIndex) return false;
1261 return VectorIndex.Val < 2;
1262 }
1263
Jim Grosbach0e387b22011-10-17 22:26:03 +00001264 bool isNEONi8splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001265 if (!isImm()) return false;
Jim Grosbach0e387b22011-10-17 22:26:03 +00001266 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1267 // Must be a constant.
1268 if (!CE) return false;
1269 int64_t Value = CE->getValue();
1270 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1271 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +00001272 return Value >= 0 && Value < 256;
1273 }
Jim Grosbach460a9052011-10-07 23:56:00 +00001274
Jim Grosbachea461102011-10-17 23:09:09 +00001275 bool isNEONi16splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001276 if (!isImm()) return false;
Jim Grosbachea461102011-10-17 23:09:09 +00001277 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1278 // Must be a constant.
1279 if (!CE) return false;
1280 int64_t Value = CE->getValue();
1281 // i16 value in the range [0,255] or [0x0100, 0xff00]
1282 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1283 }
1284
Jim Grosbach6248a542011-10-18 00:22:00 +00001285 bool isNEONi32splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001286 if (!isImm()) return false;
Jim Grosbach6248a542011-10-18 00:22:00 +00001287 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1288 // Must be a constant.
1289 if (!CE) return false;
1290 int64_t Value = CE->getValue();
1291 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1292 return (Value >= 0 && Value < 256) ||
1293 (Value >= 0x0100 && Value <= 0xff00) ||
1294 (Value >= 0x010000 && Value <= 0xff0000) ||
1295 (Value >= 0x01000000 && Value <= 0xff000000);
1296 }
1297
1298 bool isNEONi32vmov() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001299 if (!isImm()) return false;
Jim Grosbach6248a542011-10-18 00:22:00 +00001300 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1301 // Must be a constant.
1302 if (!CE) return false;
1303 int64_t Value = CE->getValue();
1304 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1305 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1306 return (Value >= 0 && Value < 256) ||
1307 (Value >= 0x0100 && Value <= 0xff00) ||
1308 (Value >= 0x010000 && Value <= 0xff0000) ||
1309 (Value >= 0x01000000 && Value <= 0xff000000) ||
1310 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1311 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1312 }
Jim Grosbach9b087852011-12-19 23:51:07 +00001313 bool isNEONi32vmovNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001314 if (!isImm()) return false;
Jim Grosbach9b087852011-12-19 23:51:07 +00001315 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1316 // Must be a constant.
1317 if (!CE) return false;
1318 int64_t Value = ~CE->getValue();
1319 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1320 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1321 return (Value >= 0 && Value < 256) ||
1322 (Value >= 0x0100 && Value <= 0xff00) ||
1323 (Value >= 0x010000 && Value <= 0xff0000) ||
1324 (Value >= 0x01000000 && Value <= 0xff000000) ||
1325 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1326 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1327 }
Jim Grosbach6248a542011-10-18 00:22:00 +00001328
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001329 bool isNEONi64splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001330 if (!isImm()) return false;
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001331 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1332 // Must be a constant.
1333 if (!CE) return false;
1334 uint64_t Value = CE->getValue();
1335 // i64 value with each byte being either 0 or 0xff.
1336 for (unsigned i = 0; i < 8; ++i)
1337 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1338 return true;
1339 }
1340
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001341 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001342 // Add as immediates when possible. Null MCExpr = 0.
1343 if (Expr == 0)
1344 Inst.addOperand(MCOperand::CreateImm(0));
1345 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001346 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1347 else
1348 Inst.addOperand(MCOperand::CreateExpr(Expr));
1349 }
1350
Daniel Dunbar8462b302010-08-11 06:36:53 +00001351 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001352 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001353 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001354 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1355 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001356 }
1357
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001358 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1359 assert(N == 1 && "Invalid number of operands!");
1360 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1361 }
1362
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001363 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1364 assert(N == 1 && "Invalid number of operands!");
1365 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1366 }
1367
1368 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1369 assert(N == 1 && "Invalid number of operands!");
1370 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1371 }
1372
Jim Grosbach89df9962011-08-26 21:43:41 +00001373 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1374 assert(N == 1 && "Invalid number of operands!");
1375 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1376 }
1377
1378 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1379 assert(N == 1 && "Invalid number of operands!");
1380 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1381 }
1382
Jim Grosbachd67641b2010-12-06 18:21:12 +00001383 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1384 assert(N == 1 && "Invalid number of operands!");
1385 Inst.addOperand(MCOperand::CreateReg(getReg()));
1386 }
1387
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001388 void addRegOperands(MCInst &Inst, unsigned N) const {
1389 assert(N == 1 && "Invalid number of operands!");
1390 Inst.addOperand(MCOperand::CreateReg(getReg()));
1391 }
1392
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001393 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001394 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001395 assert(isRegShiftedReg() &&
1396 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001397 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1398 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001399 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001400 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001401 }
1402
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001403 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001404 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001405 assert(isRegShiftedImm() &&
1406 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001407 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001408 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001409 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001410 }
1411
Jim Grosbach580f4a92011-07-25 22:20:28 +00001412 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001413 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001414 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1415 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001416 }
1417
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001418 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001419 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001420 const SmallVectorImpl<unsigned> &RegList = getRegList();
1421 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001422 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1423 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001424 }
1425
Bill Wendling0f630752010-11-17 04:32:08 +00001426 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1427 addRegListOperands(Inst, N);
1428 }
1429
1430 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1431 addRegListOperands(Inst, N);
1432 }
1433
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001434 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1435 assert(N == 1 && "Invalid number of operands!");
1436 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1437 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1438 }
1439
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001440 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1441 assert(N == 1 && "Invalid number of operands!");
1442 // Munge the lsb/width into a bitfield mask.
1443 unsigned lsb = Bitfield.LSB;
1444 unsigned width = Bitfield.Width;
1445 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1446 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1447 (32 - (lsb + width)));
1448 Inst.addOperand(MCOperand::CreateImm(Mask));
1449 }
1450
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001451 void addImmOperands(MCInst &Inst, unsigned N) const {
1452 assert(N == 1 && "Invalid number of operands!");
1453 addExpr(Inst, getImm());
1454 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001455
Jim Grosbach4050bc42011-12-22 22:19:05 +00001456 void addFBits16Operands(MCInst &Inst, unsigned N) const {
1457 assert(N == 1 && "Invalid number of operands!");
1458 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1459 Inst.addOperand(MCOperand::CreateImm(16 - CE->getValue()));
1460 }
1461
1462 void addFBits32Operands(MCInst &Inst, unsigned N) const {
1463 assert(N == 1 && "Invalid number of operands!");
1464 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1465 Inst.addOperand(MCOperand::CreateImm(32 - CE->getValue()));
1466 }
1467
Jim Grosbach9d390362011-10-03 23:38:36 +00001468 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1469 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach51222d12012-01-20 18:09:51 +00001470 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1471 int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
1472 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach9d390362011-10-03 23:38:36 +00001473 }
1474
Jim Grosbacha77295d2011-09-08 22:07:06 +00001475 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1476 assert(N == 1 && "Invalid number of operands!");
1477 // FIXME: We really want to scale the value here, but the LDRD/STRD
1478 // instruction don't encode operands that way yet.
1479 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1480 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1481 }
1482
Jim Grosbach72f39f82011-08-24 21:22:15 +00001483 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1484 assert(N == 1 && "Invalid number of operands!");
1485 // The immediate is scaled by four in the encoding and is stored
1486 // in the MCInst as such. Lop off the low two bits here.
1487 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1488 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1489 }
1490
1491 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1492 assert(N == 1 && "Invalid number of operands!");
1493 // The immediate is scaled by four in the encoding and is stored
1494 // in the MCInst as such. Lop off the low two bits here.
1495 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1496 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1497 }
1498
Jim Grosbachf4943352011-07-25 23:09:14 +00001499 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1500 assert(N == 1 && "Invalid number of operands!");
1501 // The constant encodes as the immediate-1, and we store in the instruction
1502 // the bits as encoded, so subtract off one here.
1503 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1504 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1505 }
1506
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001507 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1508 assert(N == 1 && "Invalid number of operands!");
1509 // The constant encodes as the immediate-1, and we store in the instruction
1510 // the bits as encoded, so subtract off one here.
1511 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1512 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1513 }
1514
Jim Grosbach70939ee2011-08-17 21:51:27 +00001515 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1516 assert(N == 1 && "Invalid number of operands!");
1517 // The constant encodes as the immediate, except for 32, which encodes as
1518 // zero.
1519 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1520 unsigned Imm = CE->getValue();
1521 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1522 }
1523
Jim Grosbachf6c05252011-07-21 17:23:04 +00001524 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1525 assert(N == 1 && "Invalid number of operands!");
1526 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1527 // the instruction as well.
1528 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1529 int Val = CE->getValue();
1530 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1531 }
1532
Jim Grosbach89a63372011-10-28 22:36:30 +00001533 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1534 assert(N == 1 && "Invalid number of operands!");
1535 // The operand is actually a t2_so_imm, but we have its bitwise
1536 // negation in the assembly source, so twiddle it here.
1537 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1538 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1539 }
1540
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001541 void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1542 assert(N == 1 && "Invalid number of operands!");
1543 // The operand is actually a t2_so_imm, but we have its
1544 // negation in the assembly source, so twiddle it here.
1545 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1546 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1547 }
1548
Jim Grosbache70ec842011-10-28 22:50:54 +00001549 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1550 assert(N == 1 && "Invalid number of operands!");
1551 // The operand is actually a so_imm, but we have its bitwise
1552 // negation in the assembly source, so twiddle it here.
1553 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1554 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1555 }
1556
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001557 void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
1558 assert(N == 1 && "Invalid number of operands!");
1559 // The operand is actually a so_imm, but we have its
1560 // negation in the assembly source, so twiddle it here.
1561 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1562 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1563 }
1564
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001565 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1566 assert(N == 1 && "Invalid number of operands!");
1567 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1568 }
1569
Jim Grosbach7ce05792011-08-03 23:50:40 +00001570 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1571 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001572 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001573 }
1574
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001575 void addMemPCRelImm12Operands(MCInst &Inst, unsigned N) const {
1576 assert(N == 1 && "Invalid number of operands!");
1577 int32_t Imm = Memory.OffsetImm->getValue();
1578 // FIXME: Handle #-0
1579 if (Imm == INT32_MIN) Imm = 0;
1580 Inst.addOperand(MCOperand::CreateImm(Imm));
1581 }
1582
Jim Grosbach57dcb852011-10-11 17:29:55 +00001583 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1584 assert(N == 2 && "Invalid number of operands!");
1585 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1586 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1587 }
1588
Jim Grosbach7ce05792011-08-03 23:50:40 +00001589 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1590 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001591 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1592 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001593 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1594 // Special case for #-0
1595 if (Val == INT32_MIN) Val = 0;
1596 if (Val < 0) Val = -Val;
1597 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1598 } else {
1599 // For register offset, we encode the shift type and negation flag
1600 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001601 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1602 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001603 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001604 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1605 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001606 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001607 }
1608
Jim Grosbach039c2e12011-08-04 23:01:30 +00001609 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1610 assert(N == 2 && "Invalid number of operands!");
1611 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1612 assert(CE && "non-constant AM2OffsetImm operand!");
1613 int32_t Val = CE->getValue();
1614 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1615 // Special case for #-0
1616 if (Val == INT32_MIN) Val = 0;
1617 if (Val < 0) Val = -Val;
1618 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1619 Inst.addOperand(MCOperand::CreateReg(0));
1620 Inst.addOperand(MCOperand::CreateImm(Val));
1621 }
1622
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001623 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1624 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001625 // If we have an immediate that's not a constant, treat it as a label
1626 // reference needing a fixup. If it is a constant, it's something else
1627 // and we reject it.
1628 if (isImm()) {
1629 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1630 Inst.addOperand(MCOperand::CreateReg(0));
1631 Inst.addOperand(MCOperand::CreateImm(0));
1632 return;
1633 }
1634
Jim Grosbache53c87b2011-10-11 15:59:20 +00001635 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1636 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001637 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1638 // Special case for #-0
1639 if (Val == INT32_MIN) Val = 0;
1640 if (Val < 0) Val = -Val;
1641 Val = ARM_AM::getAM3Opc(AddSub, Val);
1642 } else {
1643 // For register offset, we encode the shift type and negation flag
1644 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001645 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001646 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001647 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1648 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001649 Inst.addOperand(MCOperand::CreateImm(Val));
1650 }
1651
1652 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1653 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001654 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001655 int32_t Val =
1656 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1657 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1658 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001659 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001660 }
1661
1662 // Constant offset.
1663 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1664 int32_t Val = CE->getValue();
1665 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1666 // Special case for #-0
1667 if (Val == INT32_MIN) Val = 0;
1668 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001669 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001670 Inst.addOperand(MCOperand::CreateReg(0));
1671 Inst.addOperand(MCOperand::CreateImm(Val));
1672 }
1673
Jim Grosbach7ce05792011-08-03 23:50:40 +00001674 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1675 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach681460f2011-11-01 01:24:45 +00001676 // If we have an immediate that's not a constant, treat it as a label
1677 // reference needing a fixup. If it is a constant, it's something else
1678 // and we reject it.
1679 if (isImm()) {
1680 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1681 Inst.addOperand(MCOperand::CreateImm(0));
1682 return;
1683 }
1684
Jim Grosbach7ce05792011-08-03 23:50:40 +00001685 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001686 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001687 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1688 // Special case for #-0
1689 if (Val == INT32_MIN) Val = 0;
1690 if (Val < 0) Val = -Val;
1691 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001692 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001693 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001694 }
1695
Jim Grosbacha77295d2011-09-08 22:07:06 +00001696 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1697 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001698 // If we have an immediate that's not a constant, treat it as a label
1699 // reference needing a fixup. If it is a constant, it's something else
1700 // and we reject it.
1701 if (isImm()) {
1702 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1703 Inst.addOperand(MCOperand::CreateImm(0));
1704 return;
1705 }
1706
Jim Grosbache53c87b2011-10-11 15:59:20 +00001707 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1708 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001709 Inst.addOperand(MCOperand::CreateImm(Val));
1710 }
1711
Jim Grosbachb6aed502011-09-09 18:37:27 +00001712 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1713 assert(N == 2 && "Invalid number of operands!");
1714 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001715 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1716 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001717 Inst.addOperand(MCOperand::CreateImm(Val));
1718 }
1719
Jim Grosbach7ce05792011-08-03 23:50:40 +00001720 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1721 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001722 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1723 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001724 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001725 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001726
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001727 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1728 addMemImm8OffsetOperands(Inst, N);
1729 }
1730
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001731 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001732 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001733 }
1734
1735 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1736 assert(N == 2 && "Invalid number of operands!");
1737 // If this is an immediate, it's a label reference.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001738 if (isImm()) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001739 addExpr(Inst, getImm());
1740 Inst.addOperand(MCOperand::CreateImm(0));
1741 return;
1742 }
1743
1744 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001745 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1746 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001747 Inst.addOperand(MCOperand::CreateImm(Val));
1748 }
1749
Jim Grosbach7ce05792011-08-03 23:50:40 +00001750 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1751 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001752 // If this is an immediate, it's a label reference.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001753 if (isImm()) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001754 addExpr(Inst, getImm());
1755 Inst.addOperand(MCOperand::CreateImm(0));
1756 return;
1757 }
1758
1759 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001760 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1761 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001762 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001763 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001764
Jim Grosbach7f739be2011-09-19 22:21:13 +00001765 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1766 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001767 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1768 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001769 }
1770
1771 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1772 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001773 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1774 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001775 }
1776
Jim Grosbach7ce05792011-08-03 23:50:40 +00001777 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1778 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001779 unsigned Val =
1780 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1781 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001782 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1783 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001784 Inst.addOperand(MCOperand::CreateImm(Val));
1785 }
1786
Jim Grosbachab899c12011-09-07 23:10:15 +00001787 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1788 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001789 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1790 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1791 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001792 }
1793
Jim Grosbach7ce05792011-08-03 23:50:40 +00001794 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1795 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001796 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1797 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001798 }
1799
Jim Grosbach60f91a32011-08-19 17:55:24 +00001800 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1801 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001802 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1803 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001804 Inst.addOperand(MCOperand::CreateImm(Val));
1805 }
1806
Jim Grosbach38466302011-08-19 18:55:51 +00001807 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1808 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001809 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1810 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001811 Inst.addOperand(MCOperand::CreateImm(Val));
1812 }
1813
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001814 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1815 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001816 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1817 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001818 Inst.addOperand(MCOperand::CreateImm(Val));
1819 }
1820
Jim Grosbachecd85892011-08-19 18:13:48 +00001821 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1822 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001823 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1824 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001825 Inst.addOperand(MCOperand::CreateImm(Val));
1826 }
1827
Jim Grosbach7ce05792011-08-03 23:50:40 +00001828 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1829 assert(N == 1 && "Invalid number of operands!");
1830 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1831 assert(CE && "non-constant post-idx-imm8 operand!");
1832 int Imm = CE->getValue();
1833 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001834 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001835 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1836 Inst.addOperand(MCOperand::CreateImm(Imm));
1837 }
1838
Jim Grosbach2bd01182011-10-11 21:55:36 +00001839 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1840 assert(N == 1 && "Invalid number of operands!");
1841 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1842 assert(CE && "non-constant post-idx-imm8s4 operand!");
1843 int Imm = CE->getValue();
1844 bool isAdd = Imm >= 0;
1845 if (Imm == INT32_MIN) Imm = 0;
1846 // Immediate is scaled by 4.
1847 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1848 Inst.addOperand(MCOperand::CreateImm(Imm));
1849 }
1850
Jim Grosbach7ce05792011-08-03 23:50:40 +00001851 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1852 assert(N == 2 && "Invalid number of operands!");
1853 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001854 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1855 }
1856
1857 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1858 assert(N == 2 && "Invalid number of operands!");
1859 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1860 // The sign, shift type, and shift amount are encoded in a single operand
1861 // using the AM2 encoding helpers.
1862 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1863 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1864 PostIdxReg.ShiftTy);
1865 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001866 }
1867
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001868 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1869 assert(N == 1 && "Invalid number of operands!");
1870 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1871 }
1872
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001873 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1874 assert(N == 1 && "Invalid number of operands!");
1875 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1876 }
1877
Jim Grosbach6029b6d2011-11-29 23:51:09 +00001878 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach862019c2011-10-18 23:02:30 +00001879 assert(N == 1 && "Invalid number of operands!");
1880 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1881 }
1882
Jim Grosbach7636bf62011-12-02 00:35:16 +00001883 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1884 assert(N == 2 && "Invalid number of operands!");
1885 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1886 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1887 }
1888
Jim Grosbach460a9052011-10-07 23:56:00 +00001889 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1890 assert(N == 1 && "Invalid number of operands!");
1891 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1892 }
1893
1894 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1895 assert(N == 1 && "Invalid number of operands!");
1896 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1897 }
1898
1899 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1900 assert(N == 1 && "Invalid number of operands!");
1901 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1902 }
1903
Jim Grosbach0e387b22011-10-17 22:26:03 +00001904 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1905 assert(N == 1 && "Invalid number of operands!");
1906 // The immediate encodes the type of constant as well as the value.
1907 // Mask in that this is an i8 splat.
1908 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1909 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1910 }
1911
Jim Grosbachea461102011-10-17 23:09:09 +00001912 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1913 assert(N == 1 && "Invalid number of operands!");
1914 // The immediate encodes the type of constant as well as the value.
1915 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1916 unsigned Value = CE->getValue();
1917 if (Value >= 256)
1918 Value = (Value >> 8) | 0xa00;
1919 else
1920 Value |= 0x800;
1921 Inst.addOperand(MCOperand::CreateImm(Value));
1922 }
1923
Jim Grosbach6248a542011-10-18 00:22:00 +00001924 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1925 assert(N == 1 && "Invalid number of operands!");
1926 // The immediate encodes the type of constant as well as the value.
1927 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1928 unsigned Value = CE->getValue();
1929 if (Value >= 256 && Value <= 0xff00)
1930 Value = (Value >> 8) | 0x200;
1931 else if (Value > 0xffff && Value <= 0xff0000)
1932 Value = (Value >> 16) | 0x400;
1933 else if (Value > 0xffffff)
1934 Value = (Value >> 24) | 0x600;
1935 Inst.addOperand(MCOperand::CreateImm(Value));
1936 }
1937
1938 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1939 assert(N == 1 && "Invalid number of operands!");
1940 // The immediate encodes the type of constant as well as the value.
1941 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1942 unsigned Value = CE->getValue();
1943 if (Value >= 256 && Value <= 0xffff)
1944 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1945 else if (Value > 0xffff && Value <= 0xffffff)
1946 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1947 else if (Value > 0xffffff)
1948 Value = (Value >> 24) | 0x600;
1949 Inst.addOperand(MCOperand::CreateImm(Value));
1950 }
1951
Jim Grosbach9b087852011-12-19 23:51:07 +00001952 void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const {
1953 assert(N == 1 && "Invalid number of operands!");
1954 // The immediate encodes the type of constant as well as the value.
1955 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1956 unsigned Value = ~CE->getValue();
1957 if (Value >= 256 && Value <= 0xffff)
1958 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1959 else if (Value > 0xffff && Value <= 0xffffff)
1960 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1961 else if (Value > 0xffffff)
1962 Value = (Value >> 24) | 0x600;
1963 Inst.addOperand(MCOperand::CreateImm(Value));
1964 }
1965
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001966 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1967 assert(N == 1 && "Invalid number of operands!");
1968 // The immediate encodes the type of constant as well as the value.
1969 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1970 uint64_t Value = CE->getValue();
1971 unsigned Imm = 0;
1972 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1973 Imm |= (Value & 1) << i;
1974 }
1975 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1976 }
1977
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001978 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001979
Jim Grosbach89df9962011-08-26 21:43:41 +00001980 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001981 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001982 Op->ITMask.Mask = Mask;
1983 Op->StartLoc = S;
1984 Op->EndLoc = S;
1985 return Op;
1986 }
1987
Chris Lattner3a697562010-10-28 17:20:03 +00001988 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001989 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001990 Op->CC.Val = CC;
1991 Op->StartLoc = S;
1992 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001993 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001994 }
1995
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001996 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001997 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001998 Op->Cop.Val = CopVal;
1999 Op->StartLoc = S;
2000 Op->EndLoc = S;
2001 return Op;
2002 }
2003
2004 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002005 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002006 Op->Cop.Val = CopVal;
2007 Op->StartLoc = S;
2008 Op->EndLoc = S;
2009 return Op;
2010 }
2011
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002012 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
2013 ARMOperand *Op = new ARMOperand(k_CoprocOption);
2014 Op->Cop.Val = Val;
2015 Op->StartLoc = S;
2016 Op->EndLoc = E;
2017 return Op;
2018 }
2019
Jim Grosbachd67641b2010-12-06 18:21:12 +00002020 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002021 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00002022 Op->Reg.RegNum = RegNum;
2023 Op->StartLoc = S;
2024 Op->EndLoc = S;
2025 return Op;
2026 }
2027
Chris Lattner3a697562010-10-28 17:20:03 +00002028 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002029 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00002030 Op->Tok.Data = Str.data();
2031 Op->Tok.Length = Str.size();
2032 Op->StartLoc = S;
2033 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00002034 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002035 }
2036
Bill Wendling50d0f582010-11-18 23:43:05 +00002037 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002038 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00002039 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00002040 Op->StartLoc = S;
2041 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002042 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002043 }
2044
Jim Grosbache8606dc2011-07-13 17:50:29 +00002045 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
2046 unsigned SrcReg,
2047 unsigned ShiftReg,
2048 unsigned ShiftImm,
2049 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002050 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002051 Op->RegShiftedReg.ShiftTy = ShTy;
2052 Op->RegShiftedReg.SrcReg = SrcReg;
2053 Op->RegShiftedReg.ShiftReg = ShiftReg;
2054 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002055 Op->StartLoc = S;
2056 Op->EndLoc = E;
2057 return Op;
2058 }
2059
Owen Anderson92a20222011-07-21 18:54:16 +00002060 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
2061 unsigned SrcReg,
2062 unsigned ShiftImm,
2063 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002064 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002065 Op->RegShiftedImm.ShiftTy = ShTy;
2066 Op->RegShiftedImm.SrcReg = SrcReg;
2067 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00002068 Op->StartLoc = S;
2069 Op->EndLoc = E;
2070 return Op;
2071 }
2072
Jim Grosbach580f4a92011-07-25 22:20:28 +00002073 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002074 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002075 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00002076 Op->ShifterImm.isASR = isASR;
2077 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00002078 Op->StartLoc = S;
2079 Op->EndLoc = E;
2080 return Op;
2081 }
2082
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002083 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002084 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002085 Op->RotImm.Imm = Imm;
2086 Op->StartLoc = S;
2087 Op->EndLoc = E;
2088 return Op;
2089 }
2090
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002091 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
2092 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002093 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002094 Op->Bitfield.LSB = LSB;
2095 Op->Bitfield.Width = Width;
2096 Op->StartLoc = S;
2097 Op->EndLoc = E;
2098 return Op;
2099 }
2100
Bill Wendling7729e062010-11-09 22:44:22 +00002101 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00002102 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002103 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002104 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002105
Jim Grosbachd300b942011-09-13 22:56:44 +00002106 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002107 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00002108 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00002109 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002110 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002111
2112 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00002113 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002114 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00002115 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00002116 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002117 Op->StartLoc = StartLoc;
2118 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00002119 return Op;
2120 }
2121
Jim Grosbach862019c2011-10-18 23:02:30 +00002122 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002123 bool isDoubleSpaced, SMLoc S, SMLoc E) {
Jim Grosbach862019c2011-10-18 23:02:30 +00002124 ARMOperand *Op = new ARMOperand(k_VectorList);
2125 Op->VectorList.RegNum = RegNum;
2126 Op->VectorList.Count = Count;
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002127 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach862019c2011-10-18 23:02:30 +00002128 Op->StartLoc = S;
2129 Op->EndLoc = E;
2130 return Op;
2131 }
2132
Jim Grosbach98b05a52011-11-30 01:09:44 +00002133 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002134 bool isDoubleSpaced,
Jim Grosbach98b05a52011-11-30 01:09:44 +00002135 SMLoc S, SMLoc E) {
2136 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
2137 Op->VectorList.RegNum = RegNum;
2138 Op->VectorList.Count = Count;
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002139 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002140 Op->StartLoc = S;
2141 Op->EndLoc = E;
2142 return Op;
2143 }
2144
Jim Grosbach7636bf62011-12-02 00:35:16 +00002145 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002146 unsigned Index,
2147 bool isDoubleSpaced,
2148 SMLoc S, SMLoc E) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002149 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
2150 Op->VectorList.RegNum = RegNum;
2151 Op->VectorList.Count = Count;
2152 Op->VectorList.LaneIndex = Index;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002153 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002154 Op->StartLoc = S;
2155 Op->EndLoc = E;
2156 return Op;
2157 }
2158
Jim Grosbach460a9052011-10-07 23:56:00 +00002159 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
2160 MCContext &Ctx) {
2161 ARMOperand *Op = new ARMOperand(k_VectorIndex);
2162 Op->VectorIndex.Val = Idx;
2163 Op->StartLoc = S;
2164 Op->EndLoc = E;
2165 return Op;
2166 }
2167
Chris Lattner3a697562010-10-28 17:20:03 +00002168 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002169 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00002170 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00002171 Op->StartLoc = S;
2172 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002173 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00002174 }
2175
Jim Grosbach7ce05792011-08-03 23:50:40 +00002176 static ARMOperand *CreateMem(unsigned BaseRegNum,
2177 const MCConstantExpr *OffsetImm,
2178 unsigned OffsetRegNum,
2179 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002180 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00002181 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002182 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00002183 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002184 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00002185 Op->Memory.BaseRegNum = BaseRegNum;
2186 Op->Memory.OffsetImm = OffsetImm;
2187 Op->Memory.OffsetRegNum = OffsetRegNum;
2188 Op->Memory.ShiftType = ShiftType;
2189 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00002190 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00002191 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002192 Op->StartLoc = S;
2193 Op->EndLoc = E;
2194 return Op;
2195 }
Jim Grosbach16c74252010-10-29 14:46:02 +00002196
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002197 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
2198 ARM_AM::ShiftOpc ShiftTy,
2199 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002200 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002201 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002202 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002203 Op->PostIdxReg.isAdd = isAdd;
2204 Op->PostIdxReg.ShiftTy = ShiftTy;
2205 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00002206 Op->StartLoc = S;
2207 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002208 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002209 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002210
2211 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002212 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002213 Op->MBOpt.Val = Opt;
2214 Op->StartLoc = S;
2215 Op->EndLoc = S;
2216 return Op;
2217 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002218
2219 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002220 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002221 Op->IFlags.Val = IFlags;
2222 Op->StartLoc = S;
2223 Op->EndLoc = S;
2224 return Op;
2225 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002226
2227 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002228 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002229 Op->MMask.Val = MMask;
2230 Op->StartLoc = S;
2231 Op->EndLoc = S;
2232 return Op;
2233 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002234};
2235
2236} // end anonymous namespace.
2237
Jim Grosbachb7f689b2011-07-13 15:34:57 +00002238void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002239 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002240 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00002241 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002242 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002243 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00002244 OS << "<ccout " << getReg() << ">";
2245 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002246 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002247 static const char *MaskStr[] = {
2248 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2249 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2250 };
Jim Grosbach89df9962011-08-26 21:43:41 +00002251 assert((ITMask.Mask & 0xf) == ITMask.Mask);
2252 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2253 break;
2254 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002255 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002256 OS << "<coprocessor number: " << getCoproc() << ">";
2257 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002258 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002259 OS << "<coprocessor register: " << getCoproc() << ">";
2260 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002261 case k_CoprocOption:
2262 OS << "<coprocessor option: " << CoprocOption.Val << ">";
2263 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002264 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002265 OS << "<mask: " << getMSRMask() << ">";
2266 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002267 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002268 getImm()->print(OS);
2269 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002270 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002271 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2272 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002273 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002274 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00002275 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002276 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002277 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002278 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002279 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2280 << PostIdxReg.RegNum;
2281 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2282 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2283 << PostIdxReg.ShiftImm;
2284 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00002285 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002286 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002287 OS << "<ARM_PROC::";
2288 unsigned IFlags = getProcIFlags();
2289 for (int i=2; i >= 0; --i)
2290 if (IFlags & (1 << i))
2291 OS << ARM_PROC::IFlagsToString(1 << i);
2292 OS << ">";
2293 break;
2294 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002295 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00002296 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002297 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002298 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00002299 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2300 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00002301 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002302 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00002303 OS << "<so_reg_reg "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002304 << RegShiftedReg.SrcReg << " "
2305 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2306 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson00828302011-03-18 22:50:18 +00002307 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002308 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00002309 OS << "<so_reg_imm "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002310 << RegShiftedImm.SrcReg << " "
2311 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2312 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Anderson92a20222011-07-21 18:54:16 +00002313 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002314 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002315 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2316 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002317 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002318 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2319 << ", width: " << Bitfield.Width << ">";
2320 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002321 case k_RegisterList:
2322 case k_DPRRegisterList:
2323 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00002324 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002325
Bill Wendling5fa22a12010-11-09 23:28:44 +00002326 const SmallVectorImpl<unsigned> &RegList = getRegList();
2327 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002328 I = RegList.begin(), E = RegList.end(); I != E; ) {
2329 OS << *I;
2330 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002331 }
2332
2333 OS << ">";
2334 break;
2335 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002336 case k_VectorList:
2337 OS << "<vector_list " << VectorList.Count << " * "
2338 << VectorList.RegNum << ">";
2339 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002340 case k_VectorListAllLanes:
2341 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2342 << VectorList.RegNum << ">";
2343 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002344 case k_VectorListIndexed:
2345 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2346 << VectorList.Count << " * " << VectorList.RegNum << ">";
2347 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002348 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002349 OS << "'" << getToken() << "'";
2350 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00002351 case k_VectorIndex:
2352 OS << "<vectorindex " << getVectorIndex() << ">";
2353 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002354 }
2355}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00002356
2357/// @name Auto-generated Match Functions
2358/// {
2359
2360static unsigned MatchRegisterName(StringRef Name);
2361
2362/// }
2363
Bob Wilson69df7232011-02-03 21:46:10 +00002364bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2365 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbacha39cda72011-12-14 02:16:11 +00002366 StartLoc = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002367 RegNo = tryParseRegister();
Jim Grosbacha39cda72011-12-14 02:16:11 +00002368 EndLoc = Parser.getTok().getLoc();
Roman Divackybf755322011-01-27 17:14:22 +00002369
2370 return (RegNo == (unsigned)-1);
2371}
2372
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002373/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002374/// and if it is a register name the token is eaten and the register number is
2375/// returned. Otherwise return -1.
2376///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002377int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002378 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002379 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002380
Benjamin Kramer59085362011-11-06 20:37:06 +00002381 std::string lowerCase = Tok.getString().lower();
Owen Anderson0c9f2502011-01-13 22:50:36 +00002382 unsigned RegNum = MatchRegisterName(lowerCase);
2383 if (!RegNum) {
2384 RegNum = StringSwitch<unsigned>(lowerCase)
2385 .Case("r13", ARM::SP)
2386 .Case("r14", ARM::LR)
2387 .Case("r15", ARM::PC)
2388 .Case("ip", ARM::R12)
Jim Grosbach40e28552011-12-08 19:27:38 +00002389 // Additional register name aliases for 'gas' compatibility.
2390 .Case("a1", ARM::R0)
2391 .Case("a2", ARM::R1)
2392 .Case("a3", ARM::R2)
2393 .Case("a4", ARM::R3)
2394 .Case("v1", ARM::R4)
2395 .Case("v2", ARM::R5)
2396 .Case("v3", ARM::R6)
2397 .Case("v4", ARM::R7)
2398 .Case("v5", ARM::R8)
2399 .Case("v6", ARM::R9)
2400 .Case("v7", ARM::R10)
2401 .Case("v8", ARM::R11)
2402 .Case("sb", ARM::R9)
2403 .Case("sl", ARM::R10)
2404 .Case("fp", ARM::R11)
Owen Anderson0c9f2502011-01-13 22:50:36 +00002405 .Default(0);
2406 }
Jim Grosbacha39cda72011-12-14 02:16:11 +00002407 if (!RegNum) {
Jim Grosbachaee718b2011-12-20 23:11:00 +00002408 // Check for aliases registered via .req. Canonicalize to lower case.
2409 // That's more consistent since register names are case insensitive, and
2410 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2411 StringMap<unsigned>::const_iterator Entry = RegisterReqs.find(lowerCase);
Jim Grosbacha39cda72011-12-14 02:16:11 +00002412 // If no match, return failure.
2413 if (Entry == RegisterReqs.end())
2414 return -1;
2415 Parser.Lex(); // Eat identifier token.
2416 return Entry->getValue();
2417 }
Bob Wilson69df7232011-02-03 21:46:10 +00002418
Chris Lattnere5658fa2010-10-30 04:09:10 +00002419 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002420
Chris Lattnere5658fa2010-10-30 04:09:10 +00002421 return RegNum;
2422}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002423
Jim Grosbach19906722011-07-13 18:49:30 +00002424// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2425// If a recoverable error occurs, return 1. If an irrecoverable error
2426// occurs, return -1. An irrecoverable error is one where tokens have been
2427// consumed in the process of trying to parse the shifter (i.e., when it is
2428// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002429int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002430 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2431 SMLoc S = Parser.getTok().getLoc();
2432 const AsmToken &Tok = Parser.getTok();
2433 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2434
Benjamin Kramer59085362011-11-06 20:37:06 +00002435 std::string lowerCase = Tok.getString().lower();
Owen Anderson00828302011-03-18 22:50:18 +00002436 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbachaf4edea2011-12-07 23:40:58 +00002437 .Case("asl", ARM_AM::lsl)
Owen Anderson00828302011-03-18 22:50:18 +00002438 .Case("lsl", ARM_AM::lsl)
2439 .Case("lsr", ARM_AM::lsr)
2440 .Case("asr", ARM_AM::asr)
2441 .Case("ror", ARM_AM::ror)
2442 .Case("rrx", ARM_AM::rrx)
2443 .Default(ARM_AM::no_shift);
2444
2445 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002446 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002447
Jim Grosbache8606dc2011-07-13 17:50:29 +00002448 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002449
Jim Grosbache8606dc2011-07-13 17:50:29 +00002450 // The source register for the shift has already been added to the
2451 // operand list, so we need to pop it off and combine it into the shifted
2452 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002453 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002454 if (!PrevOp->isReg())
2455 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2456 int SrcReg = PrevOp->getReg();
2457 int64_t Imm = 0;
2458 int ShiftReg = 0;
2459 if (ShiftTy == ARM_AM::rrx) {
2460 // RRX Doesn't have an explicit shift amount. The encoder expects
2461 // the shift register to be the same as the source register. Seems odd,
2462 // but OK.
2463 ShiftReg = SrcReg;
2464 } else {
2465 // Figure out if this is shifted by a constant or a register (for non-RRX).
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00002466 if (Parser.getTok().is(AsmToken::Hash) ||
2467 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbache8606dc2011-07-13 17:50:29 +00002468 Parser.Lex(); // Eat hash.
2469 SMLoc ImmLoc = Parser.getTok().getLoc();
2470 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002471 if (getParser().ParseExpression(ShiftExpr)) {
2472 Error(ImmLoc, "invalid immediate shift value");
2473 return -1;
2474 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002475 // The expression must be evaluatable as an immediate.
2476 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002477 if (!CE) {
2478 Error(ImmLoc, "invalid immediate shift value");
2479 return -1;
2480 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002481 // Range check the immediate.
2482 // lsl, ror: 0 <= imm <= 31
2483 // lsr, asr: 0 <= imm <= 32
2484 Imm = CE->getValue();
2485 if (Imm < 0 ||
2486 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2487 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002488 Error(ImmLoc, "immediate shift value out of range");
2489 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002490 }
Jim Grosbachde626ad2011-12-22 17:37:00 +00002491 // shift by zero is a nop. Always send it through as lsl.
2492 // ('as' compatibility)
2493 if (Imm == 0)
2494 ShiftTy = ARM_AM::lsl;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002495 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002496 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002497 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002498 if (ShiftReg == -1) {
2499 Error (L, "expected immediate or register in shift operand");
2500 return -1;
2501 }
2502 } else {
2503 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002504 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002505 return -1;
2506 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002507 }
2508
Owen Anderson92a20222011-07-21 18:54:16 +00002509 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2510 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002511 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002512 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002513 else
2514 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2515 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002516
Jim Grosbach19906722011-07-13 18:49:30 +00002517 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002518}
2519
2520
Bill Wendling50d0f582010-11-18 23:43:05 +00002521/// Try to parse a register name. The token must be an Identifier when called.
2522/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2523/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002524///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002525/// TODO this is likely to change to allow different register types and or to
2526/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002527bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002528tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002529 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002530 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002531 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002532 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002533
Bill Wendling50d0f582010-11-18 23:43:05 +00002534 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002535
Chris Lattnere5658fa2010-10-30 04:09:10 +00002536 const AsmToken &ExclaimTok = Parser.getTok();
2537 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002538 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2539 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002540 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002541 return false;
2542 }
2543
2544 // Also check for an index operand. This is only legal for vector registers,
2545 // but that'll get caught OK in operand matching, so we don't need to
2546 // explicitly filter everything else out here.
2547 if (Parser.getTok().is(AsmToken::LBrac)) {
2548 SMLoc SIdx = Parser.getTok().getLoc();
2549 Parser.Lex(); // Eat left bracket token.
2550
2551 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002552 if (getParser().ParseExpression(ImmVal))
Jim Grosbach24dda212012-01-31 23:51:09 +00002553 return true;
Jim Grosbach460a9052011-10-07 23:56:00 +00002554 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbachef4d3eb2012-01-26 15:56:45 +00002555 if (!MCE)
2556 return TokError("immediate value expected for vector index");
Jim Grosbach460a9052011-10-07 23:56:00 +00002557
2558 SMLoc E = Parser.getTok().getLoc();
Jim Grosbachef4d3eb2012-01-26 15:56:45 +00002559 if (Parser.getTok().isNot(AsmToken::RBrac))
2560 return Error(E, "']' expected");
Jim Grosbach460a9052011-10-07 23:56:00 +00002561
2562 Parser.Lex(); // Eat right bracket token.
2563
2564 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2565 SIdx, E,
2566 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002567 }
2568
Bill Wendling50d0f582010-11-18 23:43:05 +00002569 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002570}
2571
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002572/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2573/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2574/// "c5", ...
2575static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002576 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2577 // but efficient.
2578 switch (Name.size()) {
David Blaikie4d6ccb52012-01-20 21:51:11 +00002579 default: return -1;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002580 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002581 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002582 return -1;
2583 switch (Name[1]) {
2584 default: return -1;
2585 case '0': return 0;
2586 case '1': return 1;
2587 case '2': return 2;
2588 case '3': return 3;
2589 case '4': return 4;
2590 case '5': return 5;
2591 case '6': return 6;
2592 case '7': return 7;
2593 case '8': return 8;
2594 case '9': return 9;
2595 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002596 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002597 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002598 return -1;
2599 switch (Name[2]) {
2600 default: return -1;
2601 case '0': return 10;
2602 case '1': return 11;
2603 case '2': return 12;
2604 case '3': return 13;
2605 case '4': return 14;
2606 case '5': return 15;
2607 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002608 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002609}
2610
Jim Grosbach89df9962011-08-26 21:43:41 +00002611/// parseITCondCode - Try to parse a condition code for an IT instruction.
2612ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2613parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2614 SMLoc S = Parser.getTok().getLoc();
2615 const AsmToken &Tok = Parser.getTok();
2616 if (!Tok.is(AsmToken::Identifier))
2617 return MatchOperand_NoMatch;
2618 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2619 .Case("eq", ARMCC::EQ)
2620 .Case("ne", ARMCC::NE)
2621 .Case("hs", ARMCC::HS)
2622 .Case("cs", ARMCC::HS)
2623 .Case("lo", ARMCC::LO)
2624 .Case("cc", ARMCC::LO)
2625 .Case("mi", ARMCC::MI)
2626 .Case("pl", ARMCC::PL)
2627 .Case("vs", ARMCC::VS)
2628 .Case("vc", ARMCC::VC)
2629 .Case("hi", ARMCC::HI)
2630 .Case("ls", ARMCC::LS)
2631 .Case("ge", ARMCC::GE)
2632 .Case("lt", ARMCC::LT)
2633 .Case("gt", ARMCC::GT)
2634 .Case("le", ARMCC::LE)
2635 .Case("al", ARMCC::AL)
2636 .Default(~0U);
2637 if (CC == ~0U)
2638 return MatchOperand_NoMatch;
2639 Parser.Lex(); // Eat the token.
2640
2641 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2642
2643 return MatchOperand_Success;
2644}
2645
Jim Grosbach43904292011-07-25 20:14:50 +00002646/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002647/// token must be an Identifier when called, and if it is a coprocessor
2648/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002649ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002650parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002651 SMLoc S = Parser.getTok().getLoc();
2652 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002653 if (Tok.isNot(AsmToken::Identifier))
2654 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002655
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002656 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002657 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002658 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002659
2660 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002661 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002662 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002663}
2664
Jim Grosbach43904292011-07-25 20:14:50 +00002665/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002666/// token must be an Identifier when called, and if it is a coprocessor
2667/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002668ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002669parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002670 SMLoc S = Parser.getTok().getLoc();
2671 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002672 if (Tok.isNot(AsmToken::Identifier))
2673 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002674
2675 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2676 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002677 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002678
2679 Parser.Lex(); // Eat identifier token.
2680 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002681 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002682}
2683
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002684/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2685/// coproc_option : '{' imm0_255 '}'
2686ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2687parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2688 SMLoc S = Parser.getTok().getLoc();
2689
2690 // If this isn't a '{', this isn't a coprocessor immediate operand.
2691 if (Parser.getTok().isNot(AsmToken::LCurly))
2692 return MatchOperand_NoMatch;
2693 Parser.Lex(); // Eat the '{'
2694
2695 const MCExpr *Expr;
2696 SMLoc Loc = Parser.getTok().getLoc();
2697 if (getParser().ParseExpression(Expr)) {
2698 Error(Loc, "illegal expression");
2699 return MatchOperand_ParseFail;
2700 }
2701 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2702 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2703 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2704 return MatchOperand_ParseFail;
2705 }
2706 int Val = CE->getValue();
2707
2708 // Check for and consume the closing '}'
2709 if (Parser.getTok().isNot(AsmToken::RCurly))
2710 return MatchOperand_ParseFail;
2711 SMLoc E = Parser.getTok().getLoc();
2712 Parser.Lex(); // Eat the '}'
2713
2714 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2715 return MatchOperand_Success;
2716}
2717
Jim Grosbachd0588e22011-09-14 18:08:35 +00002718// For register list parsing, we need to map from raw GPR register numbering
2719// to the enumeration values. The enumeration values aren't sorted by
2720// register number due to our using "sp", "lr" and "pc" as canonical names.
2721static unsigned getNextRegister(unsigned Reg) {
2722 // If this is a GPR, we need to do it manually, otherwise we can rely
2723 // on the sort ordering of the enumeration since the other reg-classes
2724 // are sane.
2725 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2726 return Reg + 1;
2727 switch(Reg) {
2728 default: assert(0 && "Invalid GPR number!");
2729 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2730 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2731 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2732 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2733 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2734 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2735 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2736 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2737 }
2738}
2739
Jim Grosbachce485e72011-11-11 21:27:40 +00002740// Return the low-subreg of a given Q register.
2741static unsigned getDRegFromQReg(unsigned QReg) {
2742 switch (QReg) {
2743 default: llvm_unreachable("expected a Q register!");
2744 case ARM::Q0: return ARM::D0;
2745 case ARM::Q1: return ARM::D2;
2746 case ARM::Q2: return ARM::D4;
2747 case ARM::Q3: return ARM::D6;
2748 case ARM::Q4: return ARM::D8;
2749 case ARM::Q5: return ARM::D10;
2750 case ARM::Q6: return ARM::D12;
2751 case ARM::Q7: return ARM::D14;
2752 case ARM::Q8: return ARM::D16;
Jim Grosbach25e0a872011-11-15 21:01:30 +00002753 case ARM::Q9: return ARM::D18;
Jim Grosbachce485e72011-11-11 21:27:40 +00002754 case ARM::Q10: return ARM::D20;
2755 case ARM::Q11: return ARM::D22;
2756 case ARM::Q12: return ARM::D24;
2757 case ARM::Q13: return ARM::D26;
2758 case ARM::Q14: return ARM::D28;
2759 case ARM::Q15: return ARM::D30;
2760 }
2761}
2762
Jim Grosbachd0588e22011-09-14 18:08:35 +00002763/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002764bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002765parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002766 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002767 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002768 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002769 Parser.Lex(); // Eat '{' token.
2770 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002771
Jim Grosbachd0588e22011-09-14 18:08:35 +00002772 // Check the first register in the list to see what register class
2773 // this is a list of.
2774 int Reg = tryParseRegister();
2775 if (Reg == -1)
2776 return Error(RegLoc, "register expected");
2777
Jim Grosbachce485e72011-11-11 21:27:40 +00002778 // The reglist instructions have at most 16 registers, so reserve
2779 // space for that many.
2780 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2781
2782 // Allow Q regs and just interpret them as the two D sub-registers.
2783 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2784 Reg = getDRegFromQReg(Reg);
2785 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2786 ++Reg;
2787 }
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002788 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002789 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2790 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2791 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2792 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2793 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2794 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2795 else
2796 return Error(RegLoc, "invalid register in register list");
2797
Jim Grosbachce485e72011-11-11 21:27:40 +00002798 // Store the register.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002799 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002800
Jim Grosbachd0588e22011-09-14 18:08:35 +00002801 // This starts immediately after the first register token in the list,
2802 // so we can see either a comma or a minus (range separator) as a legal
2803 // next token.
2804 while (Parser.getTok().is(AsmToken::Comma) ||
2805 Parser.getTok().is(AsmToken::Minus)) {
2806 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache43862b2011-11-15 23:19:15 +00002807 Parser.Lex(); // Eat the minus.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002808 SMLoc EndLoc = Parser.getTok().getLoc();
2809 int EndReg = tryParseRegister();
2810 if (EndReg == -1)
2811 return Error(EndLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002812 // Allow Q regs and just interpret them as the two D sub-registers.
2813 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2814 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002815 // If the register is the same as the start reg, there's nothing
2816 // more to do.
2817 if (Reg == EndReg)
2818 continue;
2819 // The register must be in the same register class as the first.
2820 if (!RC->contains(EndReg))
2821 return Error(EndLoc, "invalid register in register list");
2822 // Ranges must go from low to high.
2823 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2824 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002825
Jim Grosbachd0588e22011-09-14 18:08:35 +00002826 // Add all the registers in the range to the register list.
2827 while (Reg != EndReg) {
2828 Reg = getNextRegister(Reg);
2829 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2830 }
2831 continue;
2832 }
2833 Parser.Lex(); // Eat the comma.
2834 RegLoc = Parser.getTok().getLoc();
2835 int OldReg = Reg;
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002836 const AsmToken RegTok = Parser.getTok();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002837 Reg = tryParseRegister();
2838 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002839 return Error(RegLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002840 // Allow Q regs and just interpret them as the two D sub-registers.
2841 bool isQReg = false;
2842 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2843 Reg = getDRegFromQReg(Reg);
2844 isQReg = true;
2845 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002846 // The register must be in the same register class as the first.
2847 if (!RC->contains(Reg))
2848 return Error(RegLoc, "invalid register in register list");
2849 // List must be monotonically increasing.
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002850 if (getARMRegisterNumbering(Reg) < getARMRegisterNumbering(OldReg))
Jim Grosbachd0588e22011-09-14 18:08:35 +00002851 return Error(RegLoc, "register list not in ascending order");
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002852 if (getARMRegisterNumbering(Reg) == getARMRegisterNumbering(OldReg)) {
2853 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
2854 ") in register list");
2855 continue;
2856 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002857 // VFP register lists must also be contiguous.
2858 // It's OK to use the enumeration values directly here rather, as the
2859 // VFP register classes have the enum sorted properly.
2860 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2861 Reg != OldReg + 1)
2862 return Error(RegLoc, "non-contiguous register range");
2863 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbachce485e72011-11-11 21:27:40 +00002864 if (isQReg)
2865 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002866 }
2867
Jim Grosbachd0588e22011-09-14 18:08:35 +00002868 SMLoc E = Parser.getTok().getLoc();
2869 if (Parser.getTok().isNot(AsmToken::RCurly))
2870 return Error(E, "'}' expected");
2871 Parser.Lex(); // Eat '}' token.
2872
Jim Grosbach27debd62011-12-13 21:48:29 +00002873 // Push the register list operand.
Bill Wendling50d0f582010-11-18 23:43:05 +00002874 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
Jim Grosbach27debd62011-12-13 21:48:29 +00002875
2876 // The ARM system instruction variants for LDM/STM have a '^' token here.
2877 if (Parser.getTok().is(AsmToken::Caret)) {
2878 Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
2879 Parser.Lex(); // Eat '^' token.
2880 }
2881
Bill Wendling50d0f582010-11-18 23:43:05 +00002882 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002883}
2884
Jim Grosbach98b05a52011-11-30 01:09:44 +00002885// Helper function to parse the lane index for vector lists.
2886ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach7636bf62011-12-02 00:35:16 +00002887parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2888 Index = 0; // Always return a defined index value.
Jim Grosbach98b05a52011-11-30 01:09:44 +00002889 if (Parser.getTok().is(AsmToken::LBrac)) {
2890 Parser.Lex(); // Eat the '['.
2891 if (Parser.getTok().is(AsmToken::RBrac)) {
2892 // "Dn[]" is the 'all lanes' syntax.
2893 LaneKind = AllLanes;
2894 Parser.Lex(); // Eat the ']'.
2895 return MatchOperand_Success;
2896 }
Jim Grosbachc9313252011-12-21 01:19:23 +00002897 const MCExpr *LaneIndex;
2898 SMLoc Loc = Parser.getTok().getLoc();
2899 if (getParser().ParseExpression(LaneIndex)) {
2900 Error(Loc, "illegal expression");
2901 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002902 }
Jim Grosbachc9313252011-12-21 01:19:23 +00002903 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LaneIndex);
2904 if (!CE) {
2905 Error(Loc, "lane index must be empty or an integer");
2906 return MatchOperand_ParseFail;
2907 }
2908 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2909 Error(Parser.getTok().getLoc(), "']' expected");
2910 return MatchOperand_ParseFail;
2911 }
2912 Parser.Lex(); // Eat the ']'.
2913 int64_t Val = CE->getValue();
2914
2915 // FIXME: Make this range check context sensitive for .8, .16, .32.
2916 if (Val < 0 || Val > 7) {
2917 Error(Parser.getTok().getLoc(), "lane index out of range");
2918 return MatchOperand_ParseFail;
2919 }
2920 Index = Val;
2921 LaneKind = IndexedLane;
2922 return MatchOperand_Success;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002923 }
2924 LaneKind = NoLanes;
2925 return MatchOperand_Success;
2926}
2927
Jim Grosbach862019c2011-10-18 23:02:30 +00002928// parse a vector register list
2929ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2930parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002931 VectorLaneTy LaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002932 unsigned LaneIndex;
Jim Grosbach5c984e42011-11-15 21:45:55 +00002933 SMLoc S = Parser.getTok().getLoc();
2934 // As an extension (to match gas), support a plain D register or Q register
2935 // (without encosing curly braces) as a single or double entry list,
2936 // respectively.
2937 if (Parser.getTok().is(AsmToken::Identifier)) {
2938 int Reg = tryParseRegister();
2939 if (Reg == -1)
2940 return MatchOperand_NoMatch;
2941 SMLoc E = Parser.getTok().getLoc();
2942 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002943 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002944 if (Res != MatchOperand_Success)
2945 return Res;
2946 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002947 case NoLanes:
2948 E = Parser.getTok().getLoc();
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002949 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002950 break;
2951 case AllLanes:
2952 E = Parser.getTok().getLoc();
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002953 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false,
2954 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002955 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002956 case IndexedLane:
2957 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002958 LaneIndex,
2959 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00002960 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002961 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002962 return MatchOperand_Success;
2963 }
2964 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2965 Reg = getDRegFromQReg(Reg);
Jim Grosbach7636bf62011-12-02 00:35:16 +00002966 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002967 if (Res != MatchOperand_Success)
2968 return Res;
2969 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002970 case NoLanes:
2971 E = Parser.getTok().getLoc();
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002972 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002973 break;
2974 case AllLanes:
2975 E = Parser.getTok().getLoc();
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002976 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, false,
2977 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002978 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002979 case IndexedLane:
2980 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002981 LaneIndex,
2982 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00002983 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002984 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002985 return MatchOperand_Success;
2986 }
2987 Error(S, "vector register expected");
2988 return MatchOperand_ParseFail;
2989 }
2990
2991 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbach862019c2011-10-18 23:02:30 +00002992 return MatchOperand_NoMatch;
2993
Jim Grosbach862019c2011-10-18 23:02:30 +00002994 Parser.Lex(); // Eat '{' token.
2995 SMLoc RegLoc = Parser.getTok().getLoc();
2996
2997 int Reg = tryParseRegister();
2998 if (Reg == -1) {
2999 Error(RegLoc, "register expected");
3000 return MatchOperand_ParseFail;
3001 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003002 unsigned Count = 1;
Jim Grosbach276ed032011-12-15 21:54:55 +00003003 int Spacing = 0;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003004 unsigned FirstReg = Reg;
3005 // The list is of D registers, but we also allow Q regs and just interpret
3006 // them as the two D sub-registers.
3007 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
3008 FirstReg = Reg = getDRegFromQReg(Reg);
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003009 Spacing = 1; // double-spacing requires explicit D registers, otherwise
3010 // it's ambiguous with four-register single spaced.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003011 ++Reg;
3012 ++Count;
3013 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00003014 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003015 return MatchOperand_ParseFail;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003016
Jim Grosbache43862b2011-11-15 23:19:15 +00003017 while (Parser.getTok().is(AsmToken::Comma) ||
3018 Parser.getTok().is(AsmToken::Minus)) {
3019 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003020 if (!Spacing)
3021 Spacing = 1; // Register range implies a single spaced list.
3022 else if (Spacing == 2) {
3023 Error(Parser.getTok().getLoc(),
3024 "sequential registers in double spaced list");
3025 return MatchOperand_ParseFail;
3026 }
Jim Grosbache43862b2011-11-15 23:19:15 +00003027 Parser.Lex(); // Eat the minus.
3028 SMLoc EndLoc = Parser.getTok().getLoc();
3029 int EndReg = tryParseRegister();
3030 if (EndReg == -1) {
3031 Error(EndLoc, "register expected");
3032 return MatchOperand_ParseFail;
3033 }
3034 // Allow Q regs and just interpret them as the two D sub-registers.
3035 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
3036 EndReg = getDRegFromQReg(EndReg) + 1;
3037 // If the register is the same as the start reg, there's nothing
3038 // more to do.
3039 if (Reg == EndReg)
3040 continue;
3041 // The register must be in the same register class as the first.
3042 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
3043 Error(EndLoc, "invalid register in register list");
3044 return MatchOperand_ParseFail;
3045 }
3046 // Ranges must go from low to high.
3047 if (Reg > EndReg) {
3048 Error(EndLoc, "bad range in register list");
3049 return MatchOperand_ParseFail;
3050 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00003051 // Parse the lane specifier if present.
3052 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003053 unsigned NextLaneIndex;
3054 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003055 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003056 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003057 Error(EndLoc, "mismatched lane index in register list");
3058 return MatchOperand_ParseFail;
3059 }
3060 EndLoc = Parser.getTok().getLoc();
Jim Grosbache43862b2011-11-15 23:19:15 +00003061
3062 // Add all the registers in the range to the register list.
3063 Count += EndReg - Reg;
3064 Reg = EndReg;
3065 continue;
3066 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003067 Parser.Lex(); // Eat the comma.
3068 RegLoc = Parser.getTok().getLoc();
3069 int OldReg = Reg;
3070 Reg = tryParseRegister();
3071 if (Reg == -1) {
3072 Error(RegLoc, "register expected");
3073 return MatchOperand_ParseFail;
3074 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003075 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00003076 // It's OK to use the enumeration values directly here rather, as the
3077 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003078 //
3079 // The list is of D registers, but we also allow Q regs and just interpret
3080 // them as the two D sub-registers.
3081 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003082 if (!Spacing)
3083 Spacing = 1; // Register range implies a single spaced list.
3084 else if (Spacing == 2) {
3085 Error(RegLoc,
3086 "invalid register in double-spaced list (must be 'D' register')");
3087 return MatchOperand_ParseFail;
3088 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003089 Reg = getDRegFromQReg(Reg);
3090 if (Reg != OldReg + 1) {
3091 Error(RegLoc, "non-contiguous register range");
3092 return MatchOperand_ParseFail;
3093 }
3094 ++Reg;
3095 Count += 2;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003096 // Parse the lane specifier if present.
3097 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003098 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003099 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003100 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003101 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003102 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003103 Error(EndLoc, "mismatched lane index in register list");
3104 return MatchOperand_ParseFail;
3105 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003106 continue;
3107 }
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003108 // Normal D register.
3109 // Figure out the register spacing (single or double) of the list if
3110 // we don't know it already.
3111 if (!Spacing)
3112 Spacing = 1 + (Reg == OldReg + 2);
3113
3114 // Just check that it's contiguous and keep going.
3115 if (Reg != OldReg + Spacing) {
Jim Grosbach862019c2011-10-18 23:02:30 +00003116 Error(RegLoc, "non-contiguous register range");
3117 return MatchOperand_ParseFail;
3118 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003119 ++Count;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003120 // Parse the lane specifier if present.
3121 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003122 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003123 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003124 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003125 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003126 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003127 Error(EndLoc, "mismatched lane index in register list");
3128 return MatchOperand_ParseFail;
3129 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003130 }
3131
3132 SMLoc E = Parser.getTok().getLoc();
3133 if (Parser.getTok().isNot(AsmToken::RCurly)) {
3134 Error(E, "'}' expected");
3135 return MatchOperand_ParseFail;
3136 }
3137 Parser.Lex(); // Eat '}' token.
3138
Jim Grosbach98b05a52011-11-30 01:09:44 +00003139 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003140 case NoLanes:
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003141 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count,
3142 (Spacing == 2), S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003143 break;
3144 case AllLanes:
3145 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00003146 (Spacing == 2),
Jim Grosbach98b05a52011-11-30 01:09:44 +00003147 S, E));
3148 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003149 case IndexedLane:
3150 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00003151 LaneIndex,
3152 (Spacing == 2),
3153 S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00003154 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003155 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003156 return MatchOperand_Success;
3157}
3158
Jim Grosbach43904292011-07-25 20:14:50 +00003159/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00003160ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003161parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003162 SMLoc S = Parser.getTok().getLoc();
3163 const AsmToken &Tok = Parser.getTok();
3164 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3165 StringRef OptStr = Tok.getString();
3166
3167 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
3168 .Case("sy", ARM_MB::SY)
3169 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003170 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003171 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003172 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003173 .Case("ishst", ARM_MB::ISHST)
3174 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003175 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003176 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003177 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003178 .Case("osh", ARM_MB::OSH)
3179 .Case("oshst", ARM_MB::OSHST)
3180 .Default(~0U);
3181
3182 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00003183 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003184
3185 Parser.Lex(); // Eat identifier token.
3186 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00003187 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003188}
3189
Jim Grosbach43904292011-07-25 20:14:50 +00003190/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003191ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003192parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003193 SMLoc S = Parser.getTok().getLoc();
3194 const AsmToken &Tok = Parser.getTok();
3195 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3196 StringRef IFlagsStr = Tok.getString();
3197
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003198 // An iflags string of "none" is interpreted to mean that none of the AIF
3199 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003200 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003201 if (IFlagsStr != "none") {
3202 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
3203 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
3204 .Case("a", ARM_PROC::A)
3205 .Case("i", ARM_PROC::I)
3206 .Case("f", ARM_PROC::F)
3207 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003208
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003209 // If some specific iflag is already set, it means that some letter is
3210 // present more than once, this is not acceptable.
3211 if (Flag == ~0U || (IFlags & Flag))
3212 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003213
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003214 IFlags |= Flag;
3215 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003216 }
3217
3218 Parser.Lex(); // Eat identifier token.
3219 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
3220 return MatchOperand_Success;
3221}
3222
Jim Grosbach43904292011-07-25 20:14:50 +00003223/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003224ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003225parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003226 SMLoc S = Parser.getTok().getLoc();
3227 const AsmToken &Tok = Parser.getTok();
3228 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3229 StringRef Mask = Tok.getString();
3230
James Molloyacad68d2011-09-28 14:21:38 +00003231 if (isMClass()) {
3232 // See ARMv6-M 10.1.1
3233 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
3234 .Case("apsr", 0)
3235 .Case("iapsr", 1)
3236 .Case("eapsr", 2)
3237 .Case("xpsr", 3)
3238 .Case("ipsr", 5)
3239 .Case("epsr", 6)
3240 .Case("iepsr", 7)
3241 .Case("msp", 8)
3242 .Case("psp", 9)
3243 .Case("primask", 16)
3244 .Case("basepri", 17)
3245 .Case("basepri_max", 18)
3246 .Case("faultmask", 19)
3247 .Case("control", 20)
3248 .Default(~0U);
Jim Grosbach18c8d122011-12-22 17:17:10 +00003249
James Molloyacad68d2011-09-28 14:21:38 +00003250 if (FlagsVal == ~0U)
3251 return MatchOperand_NoMatch;
3252
3253 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
3254 // basepri, basepri_max and faultmask only valid for V7m.
3255 return MatchOperand_NoMatch;
Jim Grosbach18c8d122011-12-22 17:17:10 +00003256
James Molloyacad68d2011-09-28 14:21:38 +00003257 Parser.Lex(); // Eat identifier token.
3258 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3259 return MatchOperand_Success;
3260 }
3261
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003262 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
3263 size_t Start = 0, Next = Mask.find('_');
3264 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00003265 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003266 if (Next != StringRef::npos)
3267 Flags = Mask.slice(Next+1, Mask.size());
3268
3269 // FlagsVal contains the complete mask:
3270 // 3-0: Mask
3271 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3272 unsigned FlagsVal = 0;
3273
3274 if (SpecReg == "apsr") {
3275 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00003276 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003277 .Case("g", 0x4) // same as CPSR_s
3278 .Case("nzcvqg", 0xc) // same as CPSR_fs
3279 .Default(~0U);
3280
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003281 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003282 if (!Flags.empty())
3283 return MatchOperand_NoMatch;
3284 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00003285 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003286 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003287 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00003288 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
3289 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003290 for (int i = 0, e = Flags.size(); i != e; ++i) {
3291 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
3292 .Case("c", 1)
3293 .Case("x", 2)
3294 .Case("s", 4)
3295 .Case("f", 8)
3296 .Default(~0U);
3297
3298 // If some specific flag is already set, it means that some letter is
3299 // present more than once, this is not acceptable.
3300 if (FlagsVal == ~0U || (FlagsVal & Flag))
3301 return MatchOperand_NoMatch;
3302 FlagsVal |= Flag;
3303 }
3304 } else // No match for special register.
3305 return MatchOperand_NoMatch;
3306
Owen Anderson7784f1d2011-10-21 18:43:28 +00003307 // Special register without flags is NOT equivalent to "fc" flags.
3308 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3309 // two lines would enable gas compatibility at the expense of breaking
3310 // round-tripping.
3311 //
3312 // if (!FlagsVal)
3313 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003314
3315 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3316 if (SpecReg == "spsr")
3317 FlagsVal |= 16;
3318
3319 Parser.Lex(); // Eat identifier token.
3320 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3321 return MatchOperand_Success;
3322}
3323
Jim Grosbachf6c05252011-07-21 17:23:04 +00003324ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3325parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3326 int Low, int High) {
3327 const AsmToken &Tok = Parser.getTok();
3328 if (Tok.isNot(AsmToken::Identifier)) {
3329 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3330 return MatchOperand_ParseFail;
3331 }
3332 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00003333 std::string LowerOp = Op.lower();
3334 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00003335 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3336 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3337 return MatchOperand_ParseFail;
3338 }
3339 Parser.Lex(); // Eat shift type token.
3340
3341 // There must be a '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003342 if (Parser.getTok().isNot(AsmToken::Hash) &&
3343 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbachf6c05252011-07-21 17:23:04 +00003344 Error(Parser.getTok().getLoc(), "'#' expected");
3345 return MatchOperand_ParseFail;
3346 }
3347 Parser.Lex(); // Eat hash token.
3348
3349 const MCExpr *ShiftAmount;
3350 SMLoc Loc = Parser.getTok().getLoc();
3351 if (getParser().ParseExpression(ShiftAmount)) {
3352 Error(Loc, "illegal expression");
3353 return MatchOperand_ParseFail;
3354 }
3355 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3356 if (!CE) {
3357 Error(Loc, "constant expression expected");
3358 return MatchOperand_ParseFail;
3359 }
3360 int Val = CE->getValue();
3361 if (Val < Low || Val > High) {
3362 Error(Loc, "immediate value out of range");
3363 return MatchOperand_ParseFail;
3364 }
3365
3366 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3367
3368 return MatchOperand_Success;
3369}
3370
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003371ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3372parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3373 const AsmToken &Tok = Parser.getTok();
3374 SMLoc S = Tok.getLoc();
3375 if (Tok.isNot(AsmToken::Identifier)) {
3376 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3377 return MatchOperand_ParseFail;
3378 }
3379 int Val = StringSwitch<int>(Tok.getString())
3380 .Case("be", 1)
3381 .Case("le", 0)
3382 .Default(-1);
3383 Parser.Lex(); // Eat the token.
3384
3385 if (Val == -1) {
3386 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3387 return MatchOperand_ParseFail;
3388 }
3389 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3390 getContext()),
3391 S, Parser.getTok().getLoc()));
3392 return MatchOperand_Success;
3393}
3394
Jim Grosbach580f4a92011-07-25 22:20:28 +00003395/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3396/// instructions. Legal values are:
3397/// lsl #n 'n' in [0,31]
3398/// asr #n 'n' in [1,32]
3399/// n == 32 encoded as n == 0.
3400ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3401parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3402 const AsmToken &Tok = Parser.getTok();
3403 SMLoc S = Tok.getLoc();
3404 if (Tok.isNot(AsmToken::Identifier)) {
3405 Error(S, "shift operator 'asr' or 'lsl' expected");
3406 return MatchOperand_ParseFail;
3407 }
3408 StringRef ShiftName = Tok.getString();
3409 bool isASR;
3410 if (ShiftName == "lsl" || ShiftName == "LSL")
3411 isASR = false;
3412 else if (ShiftName == "asr" || ShiftName == "ASR")
3413 isASR = true;
3414 else {
3415 Error(S, "shift operator 'asr' or 'lsl' expected");
3416 return MatchOperand_ParseFail;
3417 }
3418 Parser.Lex(); // Eat the operator.
3419
3420 // A '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003421 if (Parser.getTok().isNot(AsmToken::Hash) &&
3422 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach580f4a92011-07-25 22:20:28 +00003423 Error(Parser.getTok().getLoc(), "'#' expected");
3424 return MatchOperand_ParseFail;
3425 }
3426 Parser.Lex(); // Eat hash token.
3427
3428 const MCExpr *ShiftAmount;
3429 SMLoc E = Parser.getTok().getLoc();
3430 if (getParser().ParseExpression(ShiftAmount)) {
3431 Error(E, "malformed shift expression");
3432 return MatchOperand_ParseFail;
3433 }
3434 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3435 if (!CE) {
3436 Error(E, "shift amount must be an immediate");
3437 return MatchOperand_ParseFail;
3438 }
3439
3440 int64_t Val = CE->getValue();
3441 if (isASR) {
3442 // Shift amount must be in [1,32]
3443 if (Val < 1 || Val > 32) {
3444 Error(E, "'asr' shift amount must be in range [1,32]");
3445 return MatchOperand_ParseFail;
3446 }
Owen Anderson0afa0092011-09-26 21:06:22 +00003447 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3448 if (isThumb() && Val == 32) {
3449 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3450 return MatchOperand_ParseFail;
3451 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00003452 if (Val == 32) Val = 0;
3453 } else {
3454 // Shift amount must be in [1,32]
3455 if (Val < 0 || Val > 31) {
3456 Error(E, "'lsr' shift amount must be in range [0,31]");
3457 return MatchOperand_ParseFail;
3458 }
3459 }
3460
3461 E = Parser.getTok().getLoc();
3462 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3463
3464 return MatchOperand_Success;
3465}
3466
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003467/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3468/// of instructions. Legal values are:
3469/// ror #n 'n' in {0, 8, 16, 24}
3470ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3471parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3472 const AsmToken &Tok = Parser.getTok();
3473 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00003474 if (Tok.isNot(AsmToken::Identifier))
3475 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003476 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00003477 if (ShiftName != "ror" && ShiftName != "ROR")
3478 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003479 Parser.Lex(); // Eat the operator.
3480
3481 // A '#' and a rotate amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003482 if (Parser.getTok().isNot(AsmToken::Hash) &&
3483 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003484 Error(Parser.getTok().getLoc(), "'#' expected");
3485 return MatchOperand_ParseFail;
3486 }
3487 Parser.Lex(); // Eat hash token.
3488
3489 const MCExpr *ShiftAmount;
3490 SMLoc E = Parser.getTok().getLoc();
3491 if (getParser().ParseExpression(ShiftAmount)) {
3492 Error(E, "malformed rotate expression");
3493 return MatchOperand_ParseFail;
3494 }
3495 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3496 if (!CE) {
3497 Error(E, "rotate amount must be an immediate");
3498 return MatchOperand_ParseFail;
3499 }
3500
3501 int64_t Val = CE->getValue();
3502 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3503 // normally, zero is represented in asm by omitting the rotate operand
3504 // entirely.
3505 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3506 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3507 return MatchOperand_ParseFail;
3508 }
3509
3510 E = Parser.getTok().getLoc();
3511 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3512
3513 return MatchOperand_Success;
3514}
3515
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003516ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3517parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3518 SMLoc S = Parser.getTok().getLoc();
3519 // The bitfield descriptor is really two operands, the LSB and the width.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003520 if (Parser.getTok().isNot(AsmToken::Hash) &&
3521 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003522 Error(Parser.getTok().getLoc(), "'#' expected");
3523 return MatchOperand_ParseFail;
3524 }
3525 Parser.Lex(); // Eat hash token.
3526
3527 const MCExpr *LSBExpr;
3528 SMLoc E = Parser.getTok().getLoc();
3529 if (getParser().ParseExpression(LSBExpr)) {
3530 Error(E, "malformed immediate expression");
3531 return MatchOperand_ParseFail;
3532 }
3533 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3534 if (!CE) {
3535 Error(E, "'lsb' operand must be an immediate");
3536 return MatchOperand_ParseFail;
3537 }
3538
3539 int64_t LSB = CE->getValue();
3540 // The LSB must be in the range [0,31]
3541 if (LSB < 0 || LSB > 31) {
3542 Error(E, "'lsb' operand must be in the range [0,31]");
3543 return MatchOperand_ParseFail;
3544 }
3545 E = Parser.getTok().getLoc();
3546
3547 // Expect another immediate operand.
3548 if (Parser.getTok().isNot(AsmToken::Comma)) {
3549 Error(Parser.getTok().getLoc(), "too few operands");
3550 return MatchOperand_ParseFail;
3551 }
3552 Parser.Lex(); // Eat hash token.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003553 if (Parser.getTok().isNot(AsmToken::Hash) &&
3554 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003555 Error(Parser.getTok().getLoc(), "'#' expected");
3556 return MatchOperand_ParseFail;
3557 }
3558 Parser.Lex(); // Eat hash token.
3559
3560 const MCExpr *WidthExpr;
3561 if (getParser().ParseExpression(WidthExpr)) {
3562 Error(E, "malformed immediate expression");
3563 return MatchOperand_ParseFail;
3564 }
3565 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3566 if (!CE) {
3567 Error(E, "'width' operand must be an immediate");
3568 return MatchOperand_ParseFail;
3569 }
3570
3571 int64_t Width = CE->getValue();
3572 // The LSB must be in the range [1,32-lsb]
3573 if (Width < 1 || Width > 32 - LSB) {
3574 Error(E, "'width' operand must be in the range [1,32-lsb]");
3575 return MatchOperand_ParseFail;
3576 }
3577 E = Parser.getTok().getLoc();
3578
3579 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3580
3581 return MatchOperand_Success;
3582}
3583
Jim Grosbach7ce05792011-08-03 23:50:40 +00003584ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3585parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3586 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003587 // postidx_reg := '+' register {, shift}
3588 // | '-' register {, shift}
3589 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003590
3591 // This method must return MatchOperand_NoMatch without consuming any tokens
3592 // in the case where there is no match, as other alternatives take other
3593 // parse methods.
3594 AsmToken Tok = Parser.getTok();
3595 SMLoc S = Tok.getLoc();
3596 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003597 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003598 int Reg = -1;
3599 if (Tok.is(AsmToken::Plus)) {
3600 Parser.Lex(); // Eat the '+' token.
3601 haveEaten = true;
3602 } else if (Tok.is(AsmToken::Minus)) {
3603 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003604 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003605 haveEaten = true;
3606 }
3607 if (Parser.getTok().is(AsmToken::Identifier))
3608 Reg = tryParseRegister();
3609 if (Reg == -1) {
3610 if (!haveEaten)
3611 return MatchOperand_NoMatch;
3612 Error(Parser.getTok().getLoc(), "register expected");
3613 return MatchOperand_ParseFail;
3614 }
3615 SMLoc E = Parser.getTok().getLoc();
3616
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003617 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3618 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003619 if (Parser.getTok().is(AsmToken::Comma)) {
3620 Parser.Lex(); // Eat the ','.
3621 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3622 return MatchOperand_ParseFail;
3623 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003624
3625 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3626 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003627
3628 return MatchOperand_Success;
3629}
3630
Jim Grosbach251bf252011-08-10 21:56:18 +00003631ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3632parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3633 // Check for a post-index addressing register operand. Specifically:
3634 // am3offset := '+' register
3635 // | '-' register
3636 // | register
3637 // | # imm
3638 // | # + imm
3639 // | # - imm
3640
3641 // This method must return MatchOperand_NoMatch without consuming any tokens
3642 // in the case where there is no match, as other alternatives take other
3643 // parse methods.
3644 AsmToken Tok = Parser.getTok();
3645 SMLoc S = Tok.getLoc();
3646
3647 // Do immediates first, as we always parse those if we have a '#'.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003648 if (Parser.getTok().is(AsmToken::Hash) ||
3649 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach251bf252011-08-10 21:56:18 +00003650 Parser.Lex(); // Eat the '#'.
3651 // Explicitly look for a '-', as we need to encode negative zero
3652 // differently.
3653 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3654 const MCExpr *Offset;
3655 if (getParser().ParseExpression(Offset))
3656 return MatchOperand_ParseFail;
3657 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3658 if (!CE) {
3659 Error(S, "constant expression expected");
3660 return MatchOperand_ParseFail;
3661 }
3662 SMLoc E = Tok.getLoc();
3663 // Negative zero is encoded as the flag value INT32_MIN.
3664 int32_t Val = CE->getValue();
3665 if (isNegative && Val == 0)
3666 Val = INT32_MIN;
3667
3668 Operands.push_back(
3669 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3670
3671 return MatchOperand_Success;
3672 }
3673
3674
3675 bool haveEaten = false;
3676 bool isAdd = true;
3677 int Reg = -1;
3678 if (Tok.is(AsmToken::Plus)) {
3679 Parser.Lex(); // Eat the '+' token.
3680 haveEaten = true;
3681 } else if (Tok.is(AsmToken::Minus)) {
3682 Parser.Lex(); // Eat the '-' token.
3683 isAdd = false;
3684 haveEaten = true;
3685 }
3686 if (Parser.getTok().is(AsmToken::Identifier))
3687 Reg = tryParseRegister();
3688 if (Reg == -1) {
3689 if (!haveEaten)
3690 return MatchOperand_NoMatch;
3691 Error(Parser.getTok().getLoc(), "register expected");
3692 return MatchOperand_ParseFail;
3693 }
3694 SMLoc E = Parser.getTok().getLoc();
3695
3696 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3697 0, S, E));
3698
3699 return MatchOperand_Success;
3700}
3701
Jim Grosbacha77295d2011-09-08 22:07:06 +00003702/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3703/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3704/// when they refer multiple MIOperands inside a single one.
3705bool ARMAsmParser::
3706cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3707 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3708 // Rt, Rt2
3709 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3710 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3711 // Create a writeback register dummy placeholder.
3712 Inst.addOperand(MCOperand::CreateReg(0));
3713 // addr
3714 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3715 // pred
3716 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3717 return true;
3718}
3719
3720/// cvtT2StrdPre - Convert parsed operands to MCInst.
3721/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3722/// when they refer multiple MIOperands inside a single one.
3723bool ARMAsmParser::
3724cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3725 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3726 // Create a writeback register dummy placeholder.
3727 Inst.addOperand(MCOperand::CreateReg(0));
3728 // Rt, Rt2
3729 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3730 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3731 // addr
3732 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3733 // pred
3734 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3735 return true;
3736}
3737
Jim Grosbacheeec0252011-09-08 00:39:19 +00003738/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3739/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3740/// when they refer multiple MIOperands inside a single one.
3741bool ARMAsmParser::
3742cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3743 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3744 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3745
3746 // Create a writeback register dummy placeholder.
3747 Inst.addOperand(MCOperand::CreateImm(0));
3748
3749 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3750 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3751 return true;
3752}
3753
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003754/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3755/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3756/// when they refer multiple MIOperands inside a single one.
3757bool ARMAsmParser::
3758cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3759 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3760 // Create a writeback register dummy placeholder.
3761 Inst.addOperand(MCOperand::CreateImm(0));
3762 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3763 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3764 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3765 return true;
3766}
3767
Jim Grosbach1355cf12011-07-26 17:10:22 +00003768/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003769/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3770/// when they refer multiple MIOperands inside a single one.
3771bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003772cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003773 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3774 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3775
3776 // Create a writeback register dummy placeholder.
3777 Inst.addOperand(MCOperand::CreateImm(0));
3778
Jim Grosbach7ce05792011-08-03 23:50:40 +00003779 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003780 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3781 return true;
3782}
3783
Owen Anderson9ab0f252011-08-26 20:43:14 +00003784/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3785/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3786/// when they refer multiple MIOperands inside a single one.
3787bool ARMAsmParser::
3788cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3789 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3790 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3791
3792 // Create a writeback register dummy placeholder.
3793 Inst.addOperand(MCOperand::CreateImm(0));
3794
3795 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3796 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3797 return true;
3798}
3799
3800
Jim Grosbach548340c2011-08-11 19:22:40 +00003801/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3802/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3803/// when they refer multiple MIOperands inside a single one.
3804bool ARMAsmParser::
3805cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3806 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3807 // Create a writeback register dummy placeholder.
3808 Inst.addOperand(MCOperand::CreateImm(0));
3809 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3810 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3811 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3812 return true;
3813}
3814
Jim Grosbach1355cf12011-07-26 17:10:22 +00003815/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003816/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3817/// when they refer multiple MIOperands inside a single one.
3818bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003819cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003820 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3821 // Create a writeback register dummy placeholder.
3822 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003823 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3824 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3825 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003826 return true;
3827}
3828
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003829/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3830/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3831/// when they refer multiple MIOperands inside a single one.
3832bool ARMAsmParser::
3833cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3834 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3835 // Create a writeback register dummy placeholder.
3836 Inst.addOperand(MCOperand::CreateImm(0));
3837 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3838 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3839 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3840 return true;
3841}
3842
Jim Grosbach7ce05792011-08-03 23:50:40 +00003843/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3844/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3845/// when they refer multiple MIOperands inside a single one.
3846bool ARMAsmParser::
3847cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3848 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3849 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003850 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003851 // Create a writeback register dummy placeholder.
3852 Inst.addOperand(MCOperand::CreateImm(0));
3853 // addr
3854 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3855 // offset
3856 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3857 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003858 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3859 return true;
3860}
3861
Jim Grosbach7ce05792011-08-03 23:50:40 +00003862/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003863/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3864/// when they refer multiple MIOperands inside a single one.
3865bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003866cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3867 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3868 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003869 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003870 // Create a writeback register dummy placeholder.
3871 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003872 // addr
3873 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3874 // offset
3875 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3876 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003877 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3878 return true;
3879}
3880
Jim Grosbach7ce05792011-08-03 23:50:40 +00003881/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003882/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3883/// when they refer multiple MIOperands inside a single one.
3884bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003885cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3886 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003887 // Create a writeback register dummy placeholder.
3888 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003889 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003890 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003891 // addr
3892 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3893 // offset
3894 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3895 // pred
3896 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3897 return true;
3898}
3899
3900/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3901/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3902/// when they refer multiple MIOperands inside a single one.
3903bool ARMAsmParser::
3904cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3905 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3906 // Create a writeback register dummy placeholder.
3907 Inst.addOperand(MCOperand::CreateImm(0));
3908 // Rt
3909 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3910 // addr
3911 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3912 // offset
3913 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3914 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003915 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3916 return true;
3917}
3918
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003919/// cvtLdrdPre - Convert parsed operands to MCInst.
3920/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3921/// when they refer multiple MIOperands inside a single one.
3922bool ARMAsmParser::
3923cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3924 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3925 // Rt, Rt2
3926 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3927 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3928 // Create a writeback register dummy placeholder.
3929 Inst.addOperand(MCOperand::CreateImm(0));
3930 // addr
3931 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3932 // pred
3933 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3934 return true;
3935}
3936
Jim Grosbach14605d12011-08-11 20:28:23 +00003937/// cvtStrdPre - Convert parsed operands to MCInst.
3938/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3939/// when they refer multiple MIOperands inside a single one.
3940bool ARMAsmParser::
3941cvtStrdPre(MCInst &Inst, unsigned Opcode,
3942 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3943 // Create a writeback register dummy placeholder.
3944 Inst.addOperand(MCOperand::CreateImm(0));
3945 // Rt, Rt2
3946 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3947 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3948 // addr
3949 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3950 // pred
3951 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3952 return true;
3953}
3954
Jim Grosbach623a4542011-08-10 22:42:16 +00003955/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3956/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3957/// when they refer multiple MIOperands inside a single one.
3958bool ARMAsmParser::
3959cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3960 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3961 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3962 // Create a writeback register dummy placeholder.
3963 Inst.addOperand(MCOperand::CreateImm(0));
3964 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3965 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3966 return true;
3967}
3968
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003969/// cvtThumbMultiple- Convert parsed operands to MCInst.
3970/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3971/// when they refer multiple MIOperands inside a single one.
3972bool ARMAsmParser::
3973cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3974 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3975 // The second source operand must be the same register as the destination
3976 // operand.
3977 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003978 (((ARMOperand*)Operands[3])->getReg() !=
3979 ((ARMOperand*)Operands[5])->getReg()) &&
3980 (((ARMOperand*)Operands[3])->getReg() !=
3981 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003982 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003983 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003984 return false;
3985 }
3986 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3987 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach1b332862011-11-10 22:10:12 +00003988 // If we have a three-operand form, make sure to set Rn to be the operand
3989 // that isn't the same as Rd.
3990 unsigned RegOp = 4;
3991 if (Operands.size() == 6 &&
3992 ((ARMOperand*)Operands[4])->getReg() ==
3993 ((ARMOperand*)Operands[3])->getReg())
3994 RegOp = 5;
3995 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
3996 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003997 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3998
3999 return true;
4000}
Jim Grosbach623a4542011-08-10 22:42:16 +00004001
Jim Grosbach12431322011-10-24 22:16:58 +00004002bool ARMAsmParser::
4003cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
4004 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4005 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004006 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00004007 // Create a writeback register dummy placeholder.
4008 Inst.addOperand(MCOperand::CreateImm(0));
4009 // Vn
4010 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4011 // pred
4012 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4013 return true;
4014}
4015
4016bool ARMAsmParser::
4017cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
4018 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4019 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004020 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00004021 // Create a writeback register dummy placeholder.
4022 Inst.addOperand(MCOperand::CreateImm(0));
4023 // Vn
4024 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4025 // Vm
4026 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4027 // pred
4028 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4029 return true;
4030}
4031
Jim Grosbach4334e032011-10-31 21:50:31 +00004032bool ARMAsmParser::
4033cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
4034 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4035 // Create a writeback register dummy placeholder.
4036 Inst.addOperand(MCOperand::CreateImm(0));
4037 // Vn
4038 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4039 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004040 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00004041 // pred
4042 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4043 return true;
4044}
4045
4046bool ARMAsmParser::
4047cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
4048 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4049 // Create a writeback register dummy placeholder.
4050 Inst.addOperand(MCOperand::CreateImm(0));
4051 // Vn
4052 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4053 // Vm
4054 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4055 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004056 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00004057 // pred
4058 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4059 return true;
4060}
4061
Bill Wendlinge7176102010-11-06 22:36:58 +00004062/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004063/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00004064bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00004065parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00004066 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00004067 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00004068 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00004069 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004070 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004071
Sean Callanan18b83232010-01-19 21:44:56 +00004072 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00004073 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00004074 if (BaseRegNum == -1)
4075 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004076
Daniel Dunbar05710932011-01-18 05:34:17 +00004077 // The next token must either be a comma or a closing bracket.
4078 const AsmToken &Tok = Parser.getTok();
4079 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004080 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00004081
Jim Grosbach7ce05792011-08-03 23:50:40 +00004082 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00004083 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004084 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004085
Jim Grosbach7ce05792011-08-03 23:50:40 +00004086 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004087 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00004088
Jim Grosbachfb12f352011-09-19 18:42:21 +00004089 // If there's a pre-indexing writeback marker, '!', just add it as a token
4090 // operand. It's rather odd, but syntactically valid.
4091 if (Parser.getTok().is(AsmToken::Exclaim)) {
4092 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4093 Parser.Lex(); // Eat the '!'.
4094 }
4095
Jim Grosbach7ce05792011-08-03 23:50:40 +00004096 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004097 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004098
Jim Grosbach7ce05792011-08-03 23:50:40 +00004099 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
4100 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004101
Jim Grosbach57dcb852011-10-11 17:29:55 +00004102 // If we have a ':', it's an alignment specifier.
4103 if (Parser.getTok().is(AsmToken::Colon)) {
4104 Parser.Lex(); // Eat the ':'.
4105 E = Parser.getTok().getLoc();
4106
4107 const MCExpr *Expr;
4108 if (getParser().ParseExpression(Expr))
4109 return true;
4110
4111 // The expression has to be a constant. Memory references with relocations
4112 // don't come through here, as they use the <label> forms of the relevant
4113 // instructions.
4114 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4115 if (!CE)
4116 return Error (E, "constant expression expected");
4117
4118 unsigned Align = 0;
4119 switch (CE->getValue()) {
4120 default:
Jim Grosbacheeaf1c12011-12-19 18:31:43 +00004121 return Error(E,
4122 "alignment specifier must be 16, 32, 64, 128, or 256 bits");
4123 case 16: Align = 2; break;
4124 case 32: Align = 4; break;
Jim Grosbach57dcb852011-10-11 17:29:55 +00004125 case 64: Align = 8; break;
4126 case 128: Align = 16; break;
4127 case 256: Align = 32; break;
4128 }
4129
4130 // Now we should have the closing ']'
4131 E = Parser.getTok().getLoc();
4132 if (Parser.getTok().isNot(AsmToken::RBrac))
4133 return Error(E, "']' expected");
4134 Parser.Lex(); // Eat right bracket token.
4135
4136 // Don't worry about range checking the value here. That's handled by
4137 // the is*() predicates.
4138 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
4139 ARM_AM::no_shift, 0, Align,
4140 false, S, E));
4141
4142 // If there's a pre-indexing writeback marker, '!', just add it as a token
4143 // operand.
4144 if (Parser.getTok().is(AsmToken::Exclaim)) {
4145 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4146 Parser.Lex(); // Eat the '!'.
4147 }
4148
4149 return false;
4150 }
4151
4152 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004153 // offset. Be friendly and also accept a plain integer (without a leading
4154 // hash) for gas compatibility.
4155 if (Parser.getTok().is(AsmToken::Hash) ||
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004156 Parser.getTok().is(AsmToken::Dollar) ||
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004157 Parser.getTok().is(AsmToken::Integer)) {
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004158 if (Parser.getTok().isNot(AsmToken::Integer))
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004159 Parser.Lex(); // Eat the '#'.
Jim Grosbach7ce05792011-08-03 23:50:40 +00004160 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004161
Owen Anderson0da10cf2011-08-29 19:36:44 +00004162 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00004163 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004164 if (getParser().ParseExpression(Offset))
4165 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004166
4167 // The expression has to be a constant. Memory references with relocations
4168 // don't come through here, as they use the <label> forms of the relevant
4169 // instructions.
4170 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
4171 if (!CE)
4172 return Error (E, "constant expression expected");
4173
Owen Anderson0da10cf2011-08-29 19:36:44 +00004174 // If the constant was #-0, represent it as INT32_MIN.
4175 int32_t Val = CE->getValue();
4176 if (isNegative && Val == 0)
4177 CE = MCConstantExpr::Create(INT32_MIN, getContext());
4178
Jim Grosbach7ce05792011-08-03 23:50:40 +00004179 // Now we should have the closing ']'
4180 E = Parser.getTok().getLoc();
4181 if (Parser.getTok().isNot(AsmToken::RBrac))
4182 return Error(E, "']' expected");
4183 Parser.Lex(); // Eat right bracket token.
4184
4185 // Don't worry about range checking the value here. That's handled by
4186 // the is*() predicates.
4187 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004188 ARM_AM::no_shift, 0, 0,
4189 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00004190
4191 // If there's a pre-indexing writeback marker, '!', just add it as a token
4192 // operand.
4193 if (Parser.getTok().is(AsmToken::Exclaim)) {
4194 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4195 Parser.Lex(); // Eat the '!'.
4196 }
4197
4198 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004199 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004200
4201 // The register offset is optionally preceded by a '+' or '-'
4202 bool isNegative = false;
4203 if (Parser.getTok().is(AsmToken::Minus)) {
4204 isNegative = true;
4205 Parser.Lex(); // Eat the '-'.
4206 } else if (Parser.getTok().is(AsmToken::Plus)) {
4207 // Nothing to do.
4208 Parser.Lex(); // Eat the '+'.
4209 }
4210
4211 E = Parser.getTok().getLoc();
4212 int OffsetRegNum = tryParseRegister();
4213 if (OffsetRegNum == -1)
4214 return Error(E, "register expected");
4215
4216 // If there's a shift operator, handle it.
4217 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004218 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004219 if (Parser.getTok().is(AsmToken::Comma)) {
4220 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004221 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004222 return true;
4223 }
4224
4225 // Now we should have the closing ']'
4226 E = Parser.getTok().getLoc();
4227 if (Parser.getTok().isNot(AsmToken::RBrac))
4228 return Error(E, "']' expected");
4229 Parser.Lex(); // Eat right bracket token.
4230
4231 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004232 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00004233 S, E));
4234
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00004235 // If there's a pre-indexing writeback marker, '!', just add it as a token
4236 // operand.
4237 if (Parser.getTok().is(AsmToken::Exclaim)) {
4238 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4239 Parser.Lex(); // Eat the '!'.
4240 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004241
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004242 return false;
4243}
4244
Jim Grosbach7ce05792011-08-03 23:50:40 +00004245/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004246/// ( lsl | lsr | asr | ror ) , # shift_amount
4247/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00004248/// return true if it parses a shift otherwise it returns false.
4249bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
4250 unsigned &Amount) {
4251 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00004252 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004253 if (Tok.isNot(AsmToken::Identifier))
4254 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00004255 StringRef ShiftName = Tok.getString();
Jim Grosbachaf4edea2011-12-07 23:40:58 +00004256 if (ShiftName == "lsl" || ShiftName == "LSL" ||
4257 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson00828302011-03-18 22:50:18 +00004258 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004259 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00004260 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004261 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00004262 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004263 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00004264 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004265 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00004266 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004267 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00004268 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00004269 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004270
Jim Grosbach7ce05792011-08-03 23:50:40 +00004271 // rrx stands alone.
4272 Amount = 0;
4273 if (St != ARM_AM::rrx) {
4274 Loc = Parser.getTok().getLoc();
4275 // A '#' and a shift amount.
4276 const AsmToken &HashTok = Parser.getTok();
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004277 if (HashTok.isNot(AsmToken::Hash) &&
4278 HashTok.isNot(AsmToken::Dollar))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004279 return Error(HashTok.getLoc(), "'#' expected");
4280 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004281
Jim Grosbach7ce05792011-08-03 23:50:40 +00004282 const MCExpr *Expr;
4283 if (getParser().ParseExpression(Expr))
4284 return true;
4285 // Range check the immediate.
4286 // lsl, ror: 0 <= imm <= 31
4287 // lsr, asr: 0 <= imm <= 32
4288 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4289 if (!CE)
4290 return Error(Loc, "shift amount must be an immediate");
4291 int64_t Imm = CE->getValue();
4292 if (Imm < 0 ||
4293 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4294 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4295 return Error(Loc, "immediate shift value out of range");
4296 Amount = Imm;
4297 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004298
4299 return false;
4300}
4301
Jim Grosbach9d390362011-10-03 23:38:36 +00004302/// parseFPImm - A floating point immediate expression operand.
4303ARMAsmParser::OperandMatchResultTy ARMAsmParser::
4304parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach51222d12012-01-20 18:09:51 +00004305 // Anything that can accept a floating point constant as an operand
4306 // needs to go through here, as the regular ParseExpression is
4307 // integer only.
4308 //
4309 // This routine still creates a generic Immediate operand, containing
4310 // a bitcast of the 64-bit floating point value. The various operands
4311 // that accept floats can check whether the value is valid for them
4312 // via the standard is*() predicates.
4313
Jim Grosbach9d390362011-10-03 23:38:36 +00004314 SMLoc S = Parser.getTok().getLoc();
4315
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004316 if (Parser.getTok().isNot(AsmToken::Hash) &&
4317 Parser.getTok().isNot(AsmToken::Dollar))
Jim Grosbach9d390362011-10-03 23:38:36 +00004318 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00004319
4320 // Disambiguate the VMOV forms that can accept an FP immediate.
4321 // vmov.f32 <sreg>, #imm
4322 // vmov.f64 <dreg>, #imm
4323 // vmov.f32 <dreg>, #imm @ vector f32x2
4324 // vmov.f32 <qreg>, #imm @ vector f32x4
4325 //
4326 // There are also the NEON VMOV instructions which expect an
4327 // integer constant. Make sure we don't try to parse an FPImm
4328 // for these:
4329 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4330 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4331 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4332 TyOp->getToken() != ".f64"))
4333 return MatchOperand_NoMatch;
4334
Jim Grosbach9d390362011-10-03 23:38:36 +00004335 Parser.Lex(); // Eat the '#'.
4336
4337 // Handle negation, as that still comes through as a separate token.
4338 bool isNegative = false;
4339 if (Parser.getTok().is(AsmToken::Minus)) {
4340 isNegative = true;
4341 Parser.Lex();
4342 }
4343 const AsmToken &Tok = Parser.getTok();
Jim Grosbachae69f702012-01-19 02:47:30 +00004344 SMLoc Loc = Tok.getLoc();
Jim Grosbach9d390362011-10-03 23:38:36 +00004345 if (Tok.is(AsmToken::Real)) {
Jim Grosbach51222d12012-01-20 18:09:51 +00004346 APFloat RealVal(APFloat::IEEEsingle, Tok.getString());
Jim Grosbach9d390362011-10-03 23:38:36 +00004347 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4348 // If we had a '-' in front, toggle the sign bit.
Jim Grosbach51222d12012-01-20 18:09:51 +00004349 IntVal ^= (uint64_t)isNegative << 31;
Jim Grosbach9d390362011-10-03 23:38:36 +00004350 Parser.Lex(); // Eat the token.
Jim Grosbach51222d12012-01-20 18:09:51 +00004351 Operands.push_back(ARMOperand::CreateImm(
4352 MCConstantExpr::Create(IntVal, getContext()),
4353 S, Parser.getTok().getLoc()));
Jim Grosbach9d390362011-10-03 23:38:36 +00004354 return MatchOperand_Success;
4355 }
Jim Grosbach51222d12012-01-20 18:09:51 +00004356 // Also handle plain integers. Instructions which allow floating point
4357 // immediates also allow a raw encoded 8-bit value.
Jim Grosbach9d390362011-10-03 23:38:36 +00004358 if (Tok.is(AsmToken::Integer)) {
4359 int64_t Val = Tok.getIntVal();
4360 Parser.Lex(); // Eat the token.
4361 if (Val > 255 || Val < 0) {
Jim Grosbachae69f702012-01-19 02:47:30 +00004362 Error(Loc, "encoded floating point value out of range");
Jim Grosbach9d390362011-10-03 23:38:36 +00004363 return MatchOperand_ParseFail;
4364 }
Jim Grosbach51222d12012-01-20 18:09:51 +00004365 double RealVal = ARM_AM::getFPImmFloat(Val);
4366 Val = APFloat(APFloat::IEEEdouble, RealVal).bitcastToAPInt().getZExtValue();
4367 Operands.push_back(ARMOperand::CreateImm(
4368 MCConstantExpr::Create(Val, getContext()), S,
4369 Parser.getTok().getLoc()));
Jim Grosbach9d390362011-10-03 23:38:36 +00004370 return MatchOperand_Success;
4371 }
4372
Jim Grosbachae69f702012-01-19 02:47:30 +00004373 Error(Loc, "invalid floating point immediate");
Jim Grosbach9d390362011-10-03 23:38:36 +00004374 return MatchOperand_ParseFail;
4375}
Jim Grosbach51222d12012-01-20 18:09:51 +00004376
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004377/// Parse a arm instruction operand. For now this parses the operand regardless
4378/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004379bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004380 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00004381 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004382
4383 // Check if the current operand has a custom associated parser, if so, try to
4384 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00004385 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4386 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004387 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00004388 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4389 // there was a match, but an error occurred, in which case, just return that
4390 // the operand parsing failed.
4391 if (ResTy == MatchOperand_ParseFail)
4392 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004393
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004394 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00004395 default:
4396 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00004397 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00004398 case AsmToken::Identifier: {
Jim Grosbach1355cf12011-07-26 17:10:22 +00004399 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00004400 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00004401 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00004402 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00004403 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00004404 else if (Res == -1) // irrecoverable error
4405 return true;
Jim Grosbach3cbe43f2011-12-20 22:26:38 +00004406 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004407 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
4408 S = Parser.getTok().getLoc();
4409 Parser.Lex();
4410 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
4411 return false;
4412 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00004413
4414 // Fall though for the Identifier case that is not a register or a
4415 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00004416 }
Jim Grosbach758a5192011-10-26 21:14:08 +00004417 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00004418 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00004419 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00004420 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00004421 // This was not a register so parse other operands that start with an
4422 // identifier (like labels) as expressions and create them as immediates.
4423 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00004424 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00004425 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004426 return true;
Sean Callanan76264762010-04-02 22:27:05 +00004427 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004428 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4429 return false;
4430 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004431 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004432 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00004433 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004434 return parseRegisterList(Operands);
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004435 case AsmToken::Dollar:
Owen Anderson63553c72011-08-29 17:17:09 +00004436 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00004437 // #42 -> immediate.
4438 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00004439 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004440 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00004441 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00004442 const MCExpr *ImmVal;
4443 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004444 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00004445 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbached6a0c52011-11-01 22:37:37 +00004446 if (CE) {
4447 int32_t Val = CE->getValue();
4448 if (isNegative && Val == 0)
4449 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Anderson63553c72011-08-29 17:17:09 +00004450 }
Sean Callanan76264762010-04-02 22:27:05 +00004451 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004452 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4453 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00004454 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004455 case AsmToken::Colon: {
4456 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00004457 // FIXME: Check it's an expression prefix,
4458 // e.g. (FOO - :lower16:BAR) isn't legal.
4459 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004460 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004461 return true;
4462
Evan Cheng75972122011-01-13 07:58:56 +00004463 const MCExpr *SubExprVal;
4464 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004465 return true;
4466
Evan Cheng75972122011-01-13 07:58:56 +00004467 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4468 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00004469 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00004470 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00004471 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004472 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004473 }
4474}
4475
Jim Grosbach1355cf12011-07-26 17:10:22 +00004476// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00004477// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004478bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00004479 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004480
4481 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00004482 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00004483 Parser.Lex(); // Eat ':'
4484
4485 if (getLexer().isNot(AsmToken::Identifier)) {
4486 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4487 return true;
4488 }
4489
4490 StringRef IDVal = Parser.getTok().getIdentifier();
4491 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00004492 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004493 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00004494 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004495 } else {
4496 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4497 return true;
4498 }
4499 Parser.Lex();
4500
4501 if (getLexer().isNot(AsmToken::Colon)) {
4502 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4503 return true;
4504 }
4505 Parser.Lex(); // Eat the last ':'
4506 return false;
4507}
4508
Daniel Dunbar352e1482011-01-11 15:59:50 +00004509/// \brief Given a mnemonic, split out possible predication code and carry
4510/// setting letters to form a canonical mnemonic and flags.
4511//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004512// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00004513// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004514StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00004515 unsigned &PredicationCode,
4516 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004517 unsigned &ProcessorIMod,
4518 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004519 PredicationCode = ARMCC::AL;
4520 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004521 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004522
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004523 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00004524 //
4525 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00004526 if ((Mnemonic == "movs" && isThumb()) ||
4527 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4528 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4529 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4530 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4531 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4532 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
Jim Grosbach68490192011-12-19 19:43:50 +00004533 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" ||
4534 Mnemonic == "fmuls")
Daniel Dunbar352e1482011-01-11 15:59:50 +00004535 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00004536
Jim Grosbach3f00e312011-07-11 17:09:57 +00004537 // First, split out any predication code. Ignore mnemonics we know aren't
4538 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00004539 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00004540 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00004541 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00004542 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00004543 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4544 .Case("eq", ARMCC::EQ)
4545 .Case("ne", ARMCC::NE)
4546 .Case("hs", ARMCC::HS)
4547 .Case("cs", ARMCC::HS)
4548 .Case("lo", ARMCC::LO)
4549 .Case("cc", ARMCC::LO)
4550 .Case("mi", ARMCC::MI)
4551 .Case("pl", ARMCC::PL)
4552 .Case("vs", ARMCC::VS)
4553 .Case("vc", ARMCC::VC)
4554 .Case("hi", ARMCC::HI)
4555 .Case("ls", ARMCC::LS)
4556 .Case("ge", ARMCC::GE)
4557 .Case("lt", ARMCC::LT)
4558 .Case("gt", ARMCC::GT)
4559 .Case("le", ARMCC::LE)
4560 .Case("al", ARMCC::AL)
4561 .Default(~0U);
4562 if (CC != ~0U) {
4563 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4564 PredicationCode = CC;
4565 }
Bill Wendling52925b62010-10-29 23:50:21 +00004566 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004567
Daniel Dunbar352e1482011-01-11 15:59:50 +00004568 // Next, determine if we have a carry setting bit. We explicitly ignore all
4569 // the instructions we know end in 's'.
4570 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00004571 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00004572 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4573 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4574 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach67ca1ad2011-12-08 00:49:29 +00004575 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach48171e72011-12-10 00:01:02 +00004576 Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
Jim Grosbach9c397892011-12-19 19:02:41 +00004577 Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" ||
Jim Grosbach1aa149f2011-12-22 19:20:45 +00004578 Mnemonic == "fmuls" || Mnemonic == "fcmps" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00004579 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004580 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4581 CarrySetting = true;
4582 }
4583
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004584 // The "cps" instruction can have a interrupt mode operand which is glued into
4585 // the mnemonic. Check if this is the case, split it and parse the imod op
4586 if (Mnemonic.startswith("cps")) {
4587 // Split out any imod code.
4588 unsigned IMod =
4589 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4590 .Case("ie", ARM_PROC::IE)
4591 .Case("id", ARM_PROC::ID)
4592 .Default(~0U);
4593 if (IMod != ~0U) {
4594 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4595 ProcessorIMod = IMod;
4596 }
4597 }
4598
Jim Grosbach89df9962011-08-26 21:43:41 +00004599 // The "it" instruction has the condition mask on the end of the mnemonic.
4600 if (Mnemonic.startswith("it")) {
4601 ITMask = Mnemonic.slice(2, Mnemonic.size());
4602 Mnemonic = Mnemonic.slice(0, 2);
4603 }
4604
Daniel Dunbar352e1482011-01-11 15:59:50 +00004605 return Mnemonic;
4606}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004607
4608/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4609/// inclusion of carry set or predication code operands.
4610//
4611// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004612void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00004613getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004614 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004615 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4616 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004617 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004618 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004619 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004620 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004621 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004622 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004623 Mnemonic == "mla" || Mnemonic == "smlal" ||
4624 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004625 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004626 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004627 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004628
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004629 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4630 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4631 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4632 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004633 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4634 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004635 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004636 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4637 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4638 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004639 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4640 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004641 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004642 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004643 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004644 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004645
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004646 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004647 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004648 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004649 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004650 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004651}
4652
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004653bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4654 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004655 // FIXME: This is all horribly hacky. We really need a better way to deal
4656 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004657
4658 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4659 // another does not. Specifically, the MOVW instruction does not. So we
4660 // special case it here and remove the defaulted (non-setting) cc_out
4661 // operand if that's the instruction we're trying to match.
4662 //
4663 // We do this as post-processing of the explicit operands rather than just
4664 // conditionally adding the cc_out in the first place because we need
4665 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004666 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004667 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4668 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4669 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4670 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004671
4672 // Register-register 'add' for thumb does not have a cc_out operand
4673 // when there are only two register operands.
4674 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4675 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4676 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4677 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4678 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004679 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004680 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4681 // have to check the immediate range here since Thumb2 has a variant
4682 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004683 if (((isThumb() && Mnemonic == "add") ||
4684 (isThumbTwo() && Mnemonic == "sub")) &&
4685 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004686 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4687 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4688 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004689 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4690 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4691 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004692 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004693 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4694 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004695 // selecting via the generic "add" mnemonic, so to know that we
4696 // should remove the cc_out operand, we have to explicitly check that
4697 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004698 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4699 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004700 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4701 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4702 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4703 // Nest conditions rather than one big 'if' statement for readability.
4704 //
4705 // If either register is a high reg, it's either one of the SP
4706 // variants (handled above) or a 32-bit encoding, so we just
Jim Grosbach12a88632012-01-21 00:07:56 +00004707 // check against T3. If the second register is the PC, this is an
4708 // alternate form of ADR, which uses encoding T4, so check for that too.
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004709 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4710 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
Jim Grosbach12a88632012-01-21 00:07:56 +00004711 static_cast<ARMOperand*>(Operands[4])->getReg() != ARM::PC &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004712 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4713 return false;
4714 // If both registers are low, we're in an IT block, and the immediate is
4715 // in range, we should use encoding T1 instead, which has a cc_out.
4716 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004717 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004718 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4719 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4720 return false;
4721
4722 // Otherwise, we use encoding T4, which does not have a cc_out
4723 // operand.
4724 return true;
4725 }
4726
Jim Grosbach64944f42011-09-14 21:00:40 +00004727 // The thumb2 multiply instruction doesn't have a CCOut register, so
4728 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4729 // use the 16-bit encoding or not.
4730 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4731 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4732 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4733 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4734 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4735 // If the registers aren't low regs, the destination reg isn't the
4736 // same as one of the source regs, or the cc_out operand is zero
4737 // outside of an IT block, we have to use the 32-bit encoding, so
4738 // remove the cc_out operand.
4739 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4740 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach1de0bd12011-11-15 19:29:45 +00004741 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach64944f42011-09-14 21:00:40 +00004742 !inITBlock() ||
4743 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4744 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4745 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4746 static_cast<ARMOperand*>(Operands[4])->getReg())))
4747 return true;
4748
Jim Grosbach7f1ec952011-11-15 19:55:16 +00004749 // Also check the 'mul' syntax variant that doesn't specify an explicit
4750 // destination register.
4751 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4752 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4753 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4754 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4755 // If the registers aren't low regs or the cc_out operand is zero
4756 // outside of an IT block, we have to use the 32-bit encoding, so
4757 // remove the cc_out operand.
4758 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4759 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4760 !inITBlock()))
4761 return true;
4762
Jim Grosbach64944f42011-09-14 21:00:40 +00004763
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004764
Jim Grosbachf69c8042011-08-24 21:42:27 +00004765 // Register-register 'add/sub' for thumb does not have a cc_out operand
4766 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4767 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4768 // right, this will result in better diagnostics (which operand is off)
4769 // anyway.
4770 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4771 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004772 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4773 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4774 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4775 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004776
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004777 return false;
4778}
4779
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004780static bool isDataTypeToken(StringRef Tok) {
4781 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4782 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4783 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4784 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4785 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4786 Tok == ".f" || Tok == ".d";
4787}
4788
4789// FIXME: This bit should probably be handled via an explicit match class
4790// in the .td files that matches the suffix instead of having it be
4791// a literal string token the way it is now.
4792static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4793 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4794}
4795
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004796static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004797/// Parse an arm instruction mnemonic followed by its operands.
4798bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4799 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004800 // Apply mnemonic aliases before doing anything else, as the destination
4801 // mnemnonic may include suffices and we want to handle them normally.
4802 // The generic tblgen'erated code does this later, at the start of
4803 // MatchInstructionImpl(), but that's too late for aliases that include
4804 // any sort of suffix.
4805 unsigned AvailableFeatures = getAvailableFeatures();
4806 applyMnemonicAliases(Name, AvailableFeatures);
4807
Jim Grosbacha39cda72011-12-14 02:16:11 +00004808 // First check for the ARM-specific .req directive.
4809 if (Parser.getTok().is(AsmToken::Identifier) &&
4810 Parser.getTok().getIdentifier() == ".req") {
4811 parseDirectiveReq(Name, NameLoc);
4812 // We always return 'error' for this, as we're done with this
4813 // statement and don't need to match the 'instruction."
4814 return true;
4815 }
4816
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004817 // Create the leading tokens for the mnemonic, split by '.' characters.
4818 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004819 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004820
Daniel Dunbar352e1482011-01-11 15:59:50 +00004821 // Split out the predication code and carry setting flag from the mnemonic.
4822 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004823 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004824 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004825 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004826 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004827 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004828
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004829 // In Thumb1, only the branch (B) instruction can be predicated.
4830 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4831 Parser.EatToEndOfStatement();
4832 return Error(NameLoc, "conditional execution not supported in Thumb1");
4833 }
4834
Jim Grosbachffa32252011-07-19 19:13:28 +00004835 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4836
Jim Grosbach89df9962011-08-26 21:43:41 +00004837 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4838 // is the mask as it will be for the IT encoding if the conditional
4839 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4840 // where the conditional bit0 is zero, the instruction post-processing
4841 // will adjust the mask accordingly.
4842 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004843 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4844 if (ITMask.size() > 3) {
4845 Parser.EatToEndOfStatement();
4846 return Error(Loc, "too many conditions on IT instruction");
4847 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004848 unsigned Mask = 8;
4849 for (unsigned i = ITMask.size(); i != 0; --i) {
4850 char pos = ITMask[i - 1];
4851 if (pos != 't' && pos != 'e') {
4852 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004853 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004854 }
4855 Mask >>= 1;
4856 if (ITMask[i - 1] == 't')
4857 Mask |= 8;
4858 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004859 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004860 }
4861
Jim Grosbachffa32252011-07-19 19:13:28 +00004862 // FIXME: This is all a pretty gross hack. We should automatically handle
4863 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004864
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004865 // Next, add the CCOut and ConditionCode operands, if needed.
4866 //
4867 // For mnemonics which can ever incorporate a carry setting bit or predication
4868 // code, our matching model involves us always generating CCOut and
4869 // ConditionCode operands to match the mnemonic "as written" and then we let
4870 // the matcher deal with finding the right instruction or generating an
4871 // appropriate error.
4872 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004873 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004874
Jim Grosbach33c16a22011-07-14 22:04:21 +00004875 // If we had a carry-set on an instruction that can't do that, issue an
4876 // error.
4877 if (!CanAcceptCarrySet && CarrySetting) {
4878 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004879 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004880 "' can not set flags, but 's' suffix specified");
4881 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004882 // If we had a predication code on an instruction that can't do that, issue an
4883 // error.
4884 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4885 Parser.EatToEndOfStatement();
4886 return Error(NameLoc, "instruction '" + Mnemonic +
4887 "' is not predicable, but condition code specified");
4888 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004889
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004890 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004891 if (CanAcceptCarrySet) {
4892 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004893 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004894 Loc));
4895 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004896
4897 // Add the predication code operand, if necessary.
4898 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004899 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4900 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004901 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004902 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004903 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004904
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004905 // Add the processor imod operand, if necessary.
4906 if (ProcessorIMod) {
4907 Operands.push_back(ARMOperand::CreateImm(
4908 MCConstantExpr::Create(ProcessorIMod, getContext()),
4909 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004910 }
4911
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004912 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004913 while (Next != StringRef::npos) {
4914 Start = Next;
4915 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004916 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004917
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004918 // Some NEON instructions have an optional datatype suffix that is
4919 // completely ignored. Check for that.
4920 if (isDataTypeToken(ExtraToken) &&
4921 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4922 continue;
4923
Jim Grosbach81d2e392011-09-07 16:06:04 +00004924 if (ExtraToken != ".n") {
4925 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4926 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4927 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004928 }
4929
4930 // Read the remaining operands.
4931 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004932 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004933 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004934 Parser.EatToEndOfStatement();
4935 return true;
4936 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004937
4938 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004939 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004940
4941 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004942 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004943 Parser.EatToEndOfStatement();
4944 return true;
4945 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004946 }
4947 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004948
Chris Lattnercbf8a982010-09-11 16:18:25 +00004949 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004950 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004951 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004952 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004953 }
Bill Wendling146018f2010-11-06 21:42:12 +00004954
Chris Lattner34e53142010-09-08 05:10:46 +00004955 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004956
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004957 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4958 // do and don't have a cc_out optional-def operand. With some spot-checks
4959 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004960 // parse and adjust accordingly before actually matching. We shouldn't ever
4961 // try to remove a cc_out operand that was explicitly set on the the
4962 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4963 // table driven matcher doesn't fit well with the ARM instruction set.
4964 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004965 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4966 Operands.erase(Operands.begin() + 1);
4967 delete Op;
4968 }
4969
Jim Grosbachcf121c32011-07-28 21:57:55 +00004970 // ARM mode 'blx' need special handling, as the register operand version
4971 // is predicable, but the label operand version is not. So, we can't rely
4972 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004973 // a k_CondCode operand in the list. If we're trying to match the label
4974 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004975 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4976 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4977 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4978 Operands.erase(Operands.begin() + 1);
4979 delete Op;
4980 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00004981
4982 // The vector-compare-to-zero instructions have a literal token "#0" at
4983 // the end that comes to here as an immediate operand. Convert it to a
4984 // token to play nicely with the matcher.
4985 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4986 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4987 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4988 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4989 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4990 if (CE && CE->getValue() == 0) {
4991 Operands.erase(Operands.begin() + 5);
4992 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4993 delete Op;
4994 }
4995 }
Jim Grosbach68259142011-10-03 22:30:24 +00004996 // VCMP{E} does the same thing, but with a different operand count.
4997 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4998 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4999 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
5000 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
5001 if (CE && CE->getValue() == 0) {
5002 Operands.erase(Operands.begin() + 4);
5003 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5004 delete Op;
5005 }
5006 }
Jim Grosbach934755a2011-08-22 23:47:13 +00005007 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
Jim Grosbach55b02f22011-12-13 20:50:38 +00005008 // end. Convert it to a token here. Take care not to convert those
5009 // that should hit the Thumb2 encoding.
Jim Grosbach934755a2011-08-22 23:47:13 +00005010 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
Jim Grosbach55b02f22011-12-13 20:50:38 +00005011 static_cast<ARMOperand*>(Operands[3])->isReg() &&
5012 static_cast<ARMOperand*>(Operands[4])->isReg() &&
Jim Grosbach934755a2011-08-22 23:47:13 +00005013 static_cast<ARMOperand*>(Operands[5])->isImm()) {
5014 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
5015 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
Jim Grosbach55b02f22011-12-13 20:50:38 +00005016 if (CE && CE->getValue() == 0 &&
5017 (isThumbOne() ||
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00005018 // The cc_out operand matches the IT block.
5019 ((inITBlock() != CarrySetting) &&
5020 // Neither register operand is a high register.
Jim Grosbach55b02f22011-12-13 20:50:38 +00005021 (isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00005022 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()))))){
Jim Grosbach934755a2011-08-22 23:47:13 +00005023 Operands.erase(Operands.begin() + 5);
5024 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5025 delete Op;
5026 }
5027 }
5028
Chris Lattner98986712010-01-14 22:21:20 +00005029 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005030}
5031
Jim Grosbach189610f2011-07-26 18:25:39 +00005032// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00005033
5034// return 'true' if register list contains non-low GPR registers,
5035// 'false' otherwise. If Reg is in the register list or is HiReg, set
5036// 'containsReg' to true.
5037static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
5038 unsigned HiReg, bool &containsReg) {
5039 containsReg = false;
5040 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5041 unsigned OpReg = Inst.getOperand(i).getReg();
5042 if (OpReg == Reg)
5043 containsReg = true;
5044 // Anything other than a low register isn't legal here.
5045 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
5046 return true;
5047 }
5048 return false;
5049}
5050
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005051// Check if the specified regisgter is in the register list of the inst,
5052// starting at the indicated operand number.
5053static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
5054 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5055 unsigned OpReg = Inst.getOperand(i).getReg();
5056 if (OpReg == Reg)
5057 return true;
5058 }
5059 return false;
5060}
5061
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005062// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
5063// the ARMInsts array) instead. Getting that here requires awkward
5064// API changes, though. Better way?
5065namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005066extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005067}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005068static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005069 return ARMInsts[Opcode];
5070}
5071
Jim Grosbach189610f2011-07-26 18:25:39 +00005072// FIXME: We would really like to be able to tablegen'erate this.
5073bool ARMAsmParser::
5074validateInstruction(MCInst &Inst,
5075 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005076 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005077 SMLoc Loc = Operands[0]->getStartLoc();
5078 // Check the IT block state first.
Jim Grosbach74423e32012-01-25 19:52:01 +00005079 // NOTE: BKPT instruction has the interesting property of being
5080 // allowed in IT blocks, but not being predicable. It just always
Owen Andersonb6b7f512011-09-13 17:59:19 +00005081 // executes.
Jim Grosbach74423e32012-01-25 19:52:01 +00005082 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT &&
5083 Inst.getOpcode() != ARM::BKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005084 unsigned bit = 1;
5085 if (ITState.FirstCond)
5086 ITState.FirstCond = false;
5087 else
Jim Grosbacha1109882011-09-02 23:22:08 +00005088 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005089 // The instruction must be predicable.
5090 if (!MCID.isPredicable())
5091 return Error(Loc, "instructions in IT block must be predicable");
5092 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
5093 unsigned ITCond = bit ? ITState.Cond :
5094 ARMCC::getOppositeCondition(ITState.Cond);
5095 if (Cond != ITCond) {
5096 // Find the condition code Operand to get its SMLoc information.
5097 SMLoc CondLoc;
5098 for (unsigned i = 1; i < Operands.size(); ++i)
5099 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
5100 CondLoc = Operands[i]->getStartLoc();
5101 return Error(CondLoc, "incorrect condition in IT block; got '" +
5102 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
5103 "', but expected '" +
5104 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
5105 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00005106 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005107 } else if (isThumbTwo() && MCID.isPredicable() &&
5108 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005109 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
5110 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005111 return Error(Loc, "predicated instructions must be in IT block");
5112
Jim Grosbach189610f2011-07-26 18:25:39 +00005113 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00005114 case ARM::LDRD:
5115 case ARM::LDRD_PRE:
5116 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005117 case ARM::LDREXD: {
5118 // Rt2 must be Rt + 1.
5119 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5120 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5121 if (Rt2 != Rt + 1)
5122 return Error(Operands[3]->getStartLoc(),
5123 "destination operands must be sequential");
5124 return false;
5125 }
Jim Grosbach14605d12011-08-11 20:28:23 +00005126 case ARM::STRD: {
5127 // Rt2 must be Rt + 1.
5128 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5129 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5130 if (Rt2 != Rt + 1)
5131 return Error(Operands[3]->getStartLoc(),
5132 "source operands must be sequential");
5133 return false;
5134 }
Jim Grosbach53642c52011-08-10 20:49:18 +00005135 case ARM::STRD_PRE:
5136 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005137 case ARM::STREXD: {
5138 // Rt2 must be Rt + 1.
5139 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5140 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
5141 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00005142 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00005143 "source operands must be sequential");
5144 return false;
5145 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005146 case ARM::SBFX:
5147 case ARM::UBFX: {
5148 // width must be in range [1, 32-lsb]
5149 unsigned lsb = Inst.getOperand(2).getImm();
5150 unsigned widthm1 = Inst.getOperand(3).getImm();
5151 if (widthm1 >= 32 - lsb)
5152 return Error(Operands[5]->getStartLoc(),
5153 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00005154 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005155 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005156 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005157 // If we're parsing Thumb2, the .w variant is available and handles
5158 // most cases that are normally illegal for a Thumb1 LDM
5159 // instruction. We'll make the transformation in processInstruction()
5160 // if necessary.
5161 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005162 // Thumb LDM instructions are writeback iff the base register is not
5163 // in the register list.
5164 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005165 bool hasWritebackToken =
5166 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5167 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00005168 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005169 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005170 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
5171 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005172 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005173 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005174 return Error(Operands[2]->getStartLoc(),
5175 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005176 // If we should not have writeback, there must not be a '!'. This is
5177 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00005178 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005179 return Error(Operands[3]->getStartLoc(),
5180 "writeback operator '!' not allowed when base register "
5181 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005182
5183 break;
5184 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005185 case ARM::t2LDMIA_UPD: {
5186 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
5187 return Error(Operands[4]->getStartLoc(),
5188 "writeback operator '!' not allowed when base register "
5189 "in register list");
5190 break;
5191 }
Jim Grosbach54026372011-11-10 23:17:11 +00005192 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
5193 // so only issue a diagnostic for thumb1. The instructions will be
5194 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005195 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005196 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005197 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
5198 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005199 return Error(Operands[2]->getStartLoc(),
5200 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005201 break;
5202 }
5203 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005204 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005205 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
5206 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005207 return Error(Operands[2]->getStartLoc(),
5208 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005209 break;
5210 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00005211 case ARM::tSTMIA_UPD: {
5212 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00005213 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00005214 return Error(Operands[4]->getStartLoc(),
5215 "registers must be in range r0-r7");
5216 break;
5217 }
Jim Grosbach189610f2011-07-26 18:25:39 +00005218 }
5219
5220 return false;
5221}
5222
Jim Grosbachd7433e22012-01-23 23:45:44 +00005223static unsigned getRealVSTOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach84defb52011-12-02 22:34:51 +00005224 switch(Opc) {
5225 default: assert(0 && "unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005226 // VST1LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005227 case ARM::VST1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
5228 case ARM::VST1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
5229 case ARM::VST1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
5230 case ARM::VST1LNdWB_register_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
5231 case ARM::VST1LNdWB_register_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
5232 case ARM::VST1LNdWB_register_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
5233 case ARM::VST1LNdAsm_8: Spacing = 1; return ARM::VST1LNd8;
5234 case ARM::VST1LNdAsm_16: Spacing = 1; return ARM::VST1LNd16;
5235 case ARM::VST1LNdAsm_32: Spacing = 1; return ARM::VST1LNd32;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005236
5237 // VST2LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005238 case ARM::VST2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
5239 case ARM::VST2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
5240 case ARM::VST2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
5241 case ARM::VST2LNqWB_fixed_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
5242 case ARM::VST2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005243
Jim Grosbach7945ead2012-01-24 00:43:12 +00005244 case ARM::VST2LNdWB_register_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
5245 case ARM::VST2LNdWB_register_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
5246 case ARM::VST2LNdWB_register_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
5247 case ARM::VST2LNqWB_register_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
5248 case ARM::VST2LNqWB_register_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005249
Jim Grosbach7945ead2012-01-24 00:43:12 +00005250 case ARM::VST2LNdAsm_8: Spacing = 1; return ARM::VST2LNd8;
5251 case ARM::VST2LNdAsm_16: Spacing = 1; return ARM::VST2LNd16;
5252 case ARM::VST2LNdAsm_32: Spacing = 1; return ARM::VST2LNd32;
5253 case ARM::VST2LNqAsm_16: Spacing = 2; return ARM::VST2LNq16;
5254 case ARM::VST2LNqAsm_32: Spacing = 2; return ARM::VST2LNq32;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005255
Jim Grosbach4adb1822012-01-24 00:07:41 +00005256 // VST3LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005257 case ARM::VST3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
5258 case ARM::VST3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
5259 case ARM::VST3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
5260 case ARM::VST3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNq16_UPD;
5261 case ARM::VST3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
5262 case ARM::VST3LNdWB_register_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
5263 case ARM::VST3LNdWB_register_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
5264 case ARM::VST3LNdWB_register_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
5265 case ARM::VST3LNqWB_register_Asm_16: Spacing = 2; return ARM::VST3LNq16_UPD;
5266 case ARM::VST3LNqWB_register_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
5267 case ARM::VST3LNdAsm_8: Spacing = 1; return ARM::VST3LNd8;
5268 case ARM::VST3LNdAsm_16: Spacing = 1; return ARM::VST3LNd16;
5269 case ARM::VST3LNdAsm_32: Spacing = 1; return ARM::VST3LNd32;
5270 case ARM::VST3LNqAsm_16: Spacing = 2; return ARM::VST3LNq16;
5271 case ARM::VST3LNqAsm_32: Spacing = 2; return ARM::VST3LNq32;
Jim Grosbach4adb1822012-01-24 00:07:41 +00005272
Jim Grosbachd7433e22012-01-23 23:45:44 +00005273 // VST3
Jim Grosbach7945ead2012-01-24 00:43:12 +00005274 case ARM::VST3dWB_fixed_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
5275 case ARM::VST3dWB_fixed_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
5276 case ARM::VST3dWB_fixed_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
5277 case ARM::VST3qWB_fixed_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
5278 case ARM::VST3qWB_fixed_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
5279 case ARM::VST3qWB_fixed_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
5280 case ARM::VST3dWB_register_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
5281 case ARM::VST3dWB_register_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
5282 case ARM::VST3dWB_register_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
5283 case ARM::VST3qWB_register_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
5284 case ARM::VST3qWB_register_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
5285 case ARM::VST3qWB_register_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
5286 case ARM::VST3dAsm_8: Spacing = 1; return ARM::VST3d8;
5287 case ARM::VST3dAsm_16: Spacing = 1; return ARM::VST3d16;
5288 case ARM::VST3dAsm_32: Spacing = 1; return ARM::VST3d32;
5289 case ARM::VST3qAsm_8: Spacing = 2; return ARM::VST3q8;
5290 case ARM::VST3qAsm_16: Spacing = 2; return ARM::VST3q16;
5291 case ARM::VST3qAsm_32: Spacing = 2; return ARM::VST3q32;
Jim Grosbach539aab72012-01-24 00:58:13 +00005292
Jim Grosbach88a54de2012-01-24 18:53:13 +00005293 // VST4LN
5294 case ARM::VST4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD;
5295 case ARM::VST4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD;
5296 case ARM::VST4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD;
5297 case ARM::VST4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNq16_UPD;
5298 case ARM::VST4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD;
5299 case ARM::VST4LNdWB_register_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD;
5300 case ARM::VST4LNdWB_register_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD;
5301 case ARM::VST4LNdWB_register_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD;
5302 case ARM::VST4LNqWB_register_Asm_16: Spacing = 2; return ARM::VST4LNq16_UPD;
5303 case ARM::VST4LNqWB_register_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD;
5304 case ARM::VST4LNdAsm_8: Spacing = 1; return ARM::VST4LNd8;
5305 case ARM::VST4LNdAsm_16: Spacing = 1; return ARM::VST4LNd16;
5306 case ARM::VST4LNdAsm_32: Spacing = 1; return ARM::VST4LNd32;
5307 case ARM::VST4LNqAsm_16: Spacing = 2; return ARM::VST4LNq16;
5308 case ARM::VST4LNqAsm_32: Spacing = 2; return ARM::VST4LNq32;
5309
Jim Grosbach539aab72012-01-24 00:58:13 +00005310 // VST4
5311 case ARM::VST4dWB_fixed_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
5312 case ARM::VST4dWB_fixed_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
5313 case ARM::VST4dWB_fixed_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
5314 case ARM::VST4qWB_fixed_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
5315 case ARM::VST4qWB_fixed_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
5316 case ARM::VST4qWB_fixed_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
5317 case ARM::VST4dWB_register_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
5318 case ARM::VST4dWB_register_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
5319 case ARM::VST4dWB_register_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
5320 case ARM::VST4qWB_register_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
5321 case ARM::VST4qWB_register_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
5322 case ARM::VST4qWB_register_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
5323 case ARM::VST4dAsm_8: Spacing = 1; return ARM::VST4d8;
5324 case ARM::VST4dAsm_16: Spacing = 1; return ARM::VST4d16;
5325 case ARM::VST4dAsm_32: Spacing = 1; return ARM::VST4d32;
5326 case ARM::VST4qAsm_8: Spacing = 2; return ARM::VST4q8;
5327 case ARM::VST4qAsm_16: Spacing = 2; return ARM::VST4q16;
5328 case ARM::VST4qAsm_32: Spacing = 2; return ARM::VST4q32;
Jim Grosbach84defb52011-12-02 22:34:51 +00005329 }
5330}
5331
Jim Grosbachd7433e22012-01-23 23:45:44 +00005332static unsigned getRealVLDOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005333 switch(Opc) {
5334 default: assert(0 && "unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005335 // VLD1LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005336 case ARM::VLD1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
5337 case ARM::VLD1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
5338 case ARM::VLD1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
5339 case ARM::VLD1LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
5340 case ARM::VLD1LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
5341 case ARM::VLD1LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
5342 case ARM::VLD1LNdAsm_8: Spacing = 1; return ARM::VLD1LNd8;
5343 case ARM::VLD1LNdAsm_16: Spacing = 1; return ARM::VLD1LNd16;
5344 case ARM::VLD1LNdAsm_32: Spacing = 1; return ARM::VLD1LNd32;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005345
5346 // VLD2LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005347 case ARM::VLD2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
5348 case ARM::VLD2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
5349 case ARM::VLD2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
5350 case ARM::VLD2LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNq16_UPD;
5351 case ARM::VLD2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
5352 case ARM::VLD2LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
5353 case ARM::VLD2LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
5354 case ARM::VLD2LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
5355 case ARM::VLD2LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD2LNq16_UPD;
5356 case ARM::VLD2LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
5357 case ARM::VLD2LNdAsm_8: Spacing = 1; return ARM::VLD2LNd8;
5358 case ARM::VLD2LNdAsm_16: Spacing = 1; return ARM::VLD2LNd16;
5359 case ARM::VLD2LNdAsm_32: Spacing = 1; return ARM::VLD2LNd32;
5360 case ARM::VLD2LNqAsm_16: Spacing = 2; return ARM::VLD2LNq16;
5361 case ARM::VLD2LNqAsm_32: Spacing = 2; return ARM::VLD2LNq32;
Jim Grosbach3a678af2012-01-23 21:53:26 +00005362
Jim Grosbach5e59f7e2012-01-24 23:47:04 +00005363 // VLD3DUP
5364 case ARM::VLD3DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD;
5365 case ARM::VLD3DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD;
5366 case ARM::VLD3DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD;
5367 case ARM::VLD3DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPq8_UPD;
5368 case ARM::VLD3DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPq16_UPD;
5369 case ARM::VLD3DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD;
5370 case ARM::VLD3DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD;
5371 case ARM::VLD3DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD;
5372 case ARM::VLD3DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD;
5373 case ARM::VLD3DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD3DUPq8_UPD;
5374 case ARM::VLD3DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD3DUPq16_UPD;
5375 case ARM::VLD3DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD;
5376 case ARM::VLD3DUPdAsm_8: Spacing = 1; return ARM::VLD3DUPd8;
5377 case ARM::VLD3DUPdAsm_16: Spacing = 1; return ARM::VLD3DUPd16;
5378 case ARM::VLD3DUPdAsm_32: Spacing = 1; return ARM::VLD3DUPd32;
5379 case ARM::VLD3DUPqAsm_8: Spacing = 2; return ARM::VLD3DUPq8;
5380 case ARM::VLD3DUPqAsm_16: Spacing = 2; return ARM::VLD3DUPq16;
5381 case ARM::VLD3DUPqAsm_32: Spacing = 2; return ARM::VLD3DUPq32;
5382
Jim Grosbach3a678af2012-01-23 21:53:26 +00005383 // VLD3LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005384 case ARM::VLD3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
5385 case ARM::VLD3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
5386 case ARM::VLD3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
5387 case ARM::VLD3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNq16_UPD;
5388 case ARM::VLD3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
5389 case ARM::VLD3LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
5390 case ARM::VLD3LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
5391 case ARM::VLD3LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
5392 case ARM::VLD3LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD3LNq16_UPD;
5393 case ARM::VLD3LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
5394 case ARM::VLD3LNdAsm_8: Spacing = 1; return ARM::VLD3LNd8;
5395 case ARM::VLD3LNdAsm_16: Spacing = 1; return ARM::VLD3LNd16;
5396 case ARM::VLD3LNdAsm_32: Spacing = 1; return ARM::VLD3LNd32;
5397 case ARM::VLD3LNqAsm_16: Spacing = 2; return ARM::VLD3LNq16;
5398 case ARM::VLD3LNqAsm_32: Spacing = 2; return ARM::VLD3LNq32;
Jim Grosbachc387fc62012-01-23 23:20:46 +00005399
5400 // VLD3
Jim Grosbach7945ead2012-01-24 00:43:12 +00005401 case ARM::VLD3dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
5402 case ARM::VLD3dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
5403 case ARM::VLD3dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
5404 case ARM::VLD3qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
5405 case ARM::VLD3qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
5406 case ARM::VLD3qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
5407 case ARM::VLD3dWB_register_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
5408 case ARM::VLD3dWB_register_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
5409 case ARM::VLD3dWB_register_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
5410 case ARM::VLD3qWB_register_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
5411 case ARM::VLD3qWB_register_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
5412 case ARM::VLD3qWB_register_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
5413 case ARM::VLD3dAsm_8: Spacing = 1; return ARM::VLD3d8;
5414 case ARM::VLD3dAsm_16: Spacing = 1; return ARM::VLD3d16;
5415 case ARM::VLD3dAsm_32: Spacing = 1; return ARM::VLD3d32;
5416 case ARM::VLD3qAsm_8: Spacing = 2; return ARM::VLD3q8;
5417 case ARM::VLD3qAsm_16: Spacing = 2; return ARM::VLD3q16;
5418 case ARM::VLD3qAsm_32: Spacing = 2; return ARM::VLD3q32;
Jim Grosbach8abe7e32012-01-24 00:43:17 +00005419
Jim Grosbache983a132012-01-24 18:37:25 +00005420 // VLD4LN
5421 case ARM::VLD4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD;
5422 case ARM::VLD4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
5423 case ARM::VLD4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
5424 case ARM::VLD4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNq16_UPD;
5425 case ARM::VLD4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
5426 case ARM::VLD4LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD;
5427 case ARM::VLD4LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
5428 case ARM::VLD4LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
5429 case ARM::VLD4LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD4LNq16_UPD;
5430 case ARM::VLD4LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
5431 case ARM::VLD4LNdAsm_8: Spacing = 1; return ARM::VLD4LNd8;
5432 case ARM::VLD4LNdAsm_16: Spacing = 1; return ARM::VLD4LNd16;
5433 case ARM::VLD4LNdAsm_32: Spacing = 1; return ARM::VLD4LNd32;
5434 case ARM::VLD4LNqAsm_16: Spacing = 2; return ARM::VLD4LNq16;
5435 case ARM::VLD4LNqAsm_32: Spacing = 2; return ARM::VLD4LNq32;
5436
Jim Grosbacha57a36a2012-01-25 00:01:08 +00005437 // VLD4DUP
5438 case ARM::VLD4DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD;
5439 case ARM::VLD4DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD;
5440 case ARM::VLD4DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD;
5441 case ARM::VLD4DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPq8_UPD;
5442 case ARM::VLD4DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPq16_UPD;
5443 case ARM::VLD4DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD;
5444 case ARM::VLD4DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD;
5445 case ARM::VLD4DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD;
5446 case ARM::VLD4DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD;
5447 case ARM::VLD4DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD4DUPq8_UPD;
5448 case ARM::VLD4DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD4DUPq16_UPD;
5449 case ARM::VLD4DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD;
5450 case ARM::VLD4DUPdAsm_8: Spacing = 1; return ARM::VLD4DUPd8;
5451 case ARM::VLD4DUPdAsm_16: Spacing = 1; return ARM::VLD4DUPd16;
5452 case ARM::VLD4DUPdAsm_32: Spacing = 1; return ARM::VLD4DUPd32;
5453 case ARM::VLD4DUPqAsm_8: Spacing = 2; return ARM::VLD4DUPq8;
5454 case ARM::VLD4DUPqAsm_16: Spacing = 2; return ARM::VLD4DUPq16;
5455 case ARM::VLD4DUPqAsm_32: Spacing = 2; return ARM::VLD4DUPq32;
5456
Jim Grosbach8abe7e32012-01-24 00:43:17 +00005457 // VLD4
5458 case ARM::VLD4dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
5459 case ARM::VLD4dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
5460 case ARM::VLD4dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
5461 case ARM::VLD4qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
5462 case ARM::VLD4qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
5463 case ARM::VLD4qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
5464 case ARM::VLD4dWB_register_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
5465 case ARM::VLD4dWB_register_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
5466 case ARM::VLD4dWB_register_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
5467 case ARM::VLD4qWB_register_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
5468 case ARM::VLD4qWB_register_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
5469 case ARM::VLD4qWB_register_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
5470 case ARM::VLD4dAsm_8: Spacing = 1; return ARM::VLD4d8;
5471 case ARM::VLD4dAsm_16: Spacing = 1; return ARM::VLD4d16;
5472 case ARM::VLD4dAsm_32: Spacing = 1; return ARM::VLD4d32;
5473 case ARM::VLD4qAsm_8: Spacing = 2; return ARM::VLD4q8;
5474 case ARM::VLD4qAsm_16: Spacing = 2; return ARM::VLD4q16;
5475 case ARM::VLD4qAsm_32: Spacing = 2; return ARM::VLD4q32;
Jim Grosbach7636bf62011-12-02 00:35:16 +00005476 }
5477}
5478
Jim Grosbach83ec8772011-11-10 23:42:14 +00005479bool ARMAsmParser::
Jim Grosbachf8fce712011-08-11 17:35:48 +00005480processInstruction(MCInst &Inst,
5481 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5482 switch (Inst.getOpcode()) {
Jim Grosbach0b4c6732012-01-18 22:46:46 +00005483 // Aliases for alternate PC+imm syntax of LDR instructions.
5484 case ARM::t2LDRpcrel:
5485 Inst.setOpcode(ARM::t2LDRpci);
5486 return true;
5487 case ARM::t2LDRBpcrel:
5488 Inst.setOpcode(ARM::t2LDRBpci);
5489 return true;
5490 case ARM::t2LDRHpcrel:
5491 Inst.setOpcode(ARM::t2LDRHpci);
5492 return true;
5493 case ARM::t2LDRSBpcrel:
5494 Inst.setOpcode(ARM::t2LDRSBpci);
5495 return true;
5496 case ARM::t2LDRSHpcrel:
5497 Inst.setOpcode(ARM::t2LDRSHpci);
5498 return true;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005499 // Handle NEON VST complex aliases.
Jim Grosbach8b31f952012-01-23 19:39:08 +00005500 case ARM::VST1LNdWB_register_Asm_8:
5501 case ARM::VST1LNdWB_register_Asm_16:
5502 case ARM::VST1LNdWB_register_Asm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005503 MCInst TmpInst;
5504 // Shuffle the operands around so the lane index operand is in the
5505 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005506 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005507 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005508 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5509 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5510 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5511 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5512 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5513 TmpInst.addOperand(Inst.getOperand(1)); // lane
5514 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5515 TmpInst.addOperand(Inst.getOperand(6));
5516 Inst = TmpInst;
5517 return true;
5518 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005519
Jim Grosbach8b31f952012-01-23 19:39:08 +00005520 case ARM::VST2LNdWB_register_Asm_8:
5521 case ARM::VST2LNdWB_register_Asm_16:
5522 case ARM::VST2LNdWB_register_Asm_32:
5523 case ARM::VST2LNqWB_register_Asm_16:
5524 case ARM::VST2LNqWB_register_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005525 MCInst TmpInst;
5526 // Shuffle the operands around so the lane index operand is in the
5527 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005528 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005529 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005530 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5531 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5532 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5533 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5534 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005535 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5536 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005537 TmpInst.addOperand(Inst.getOperand(1)); // lane
5538 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5539 TmpInst.addOperand(Inst.getOperand(6));
5540 Inst = TmpInst;
5541 return true;
5542 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005543
5544 case ARM::VST3LNdWB_register_Asm_8:
5545 case ARM::VST3LNdWB_register_Asm_16:
5546 case ARM::VST3LNdWB_register_Asm_32:
5547 case ARM::VST3LNqWB_register_Asm_16:
5548 case ARM::VST3LNqWB_register_Asm_32: {
5549 MCInst TmpInst;
5550 // Shuffle the operands around so the lane index operand is in the
5551 // right place.
5552 unsigned Spacing;
5553 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5554 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5555 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5556 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5557 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5558 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5559 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5560 Spacing));
5561 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5562 Spacing * 2));
5563 TmpInst.addOperand(Inst.getOperand(1)); // lane
5564 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5565 TmpInst.addOperand(Inst.getOperand(6));
5566 Inst = TmpInst;
5567 return true;
5568 }
5569
Jim Grosbach88a54de2012-01-24 18:53:13 +00005570 case ARM::VST4LNdWB_register_Asm_8:
5571 case ARM::VST4LNdWB_register_Asm_16:
5572 case ARM::VST4LNdWB_register_Asm_32:
5573 case ARM::VST4LNqWB_register_Asm_16:
5574 case ARM::VST4LNqWB_register_Asm_32: {
5575 MCInst TmpInst;
5576 // Shuffle the operands around so the lane index operand is in the
5577 // right place.
5578 unsigned Spacing;
5579 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5580 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5581 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5582 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5583 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5584 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5585 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5586 Spacing));
5587 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5588 Spacing * 2));
5589 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5590 Spacing * 3));
5591 TmpInst.addOperand(Inst.getOperand(1)); // lane
5592 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5593 TmpInst.addOperand(Inst.getOperand(6));
5594 Inst = TmpInst;
5595 return true;
5596 }
5597
Jim Grosbach8b31f952012-01-23 19:39:08 +00005598 case ARM::VST1LNdWB_fixed_Asm_8:
5599 case ARM::VST1LNdWB_fixed_Asm_16:
5600 case ARM::VST1LNdWB_fixed_Asm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005601 MCInst TmpInst;
5602 // Shuffle the operands around so the lane index operand is in the
5603 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005604 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005605 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005606 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5607 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5608 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5609 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5610 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5611 TmpInst.addOperand(Inst.getOperand(1)); // lane
5612 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5613 TmpInst.addOperand(Inst.getOperand(5));
5614 Inst = TmpInst;
5615 return true;
5616 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005617
Jim Grosbach8b31f952012-01-23 19:39:08 +00005618 case ARM::VST2LNdWB_fixed_Asm_8:
5619 case ARM::VST2LNdWB_fixed_Asm_16:
5620 case ARM::VST2LNdWB_fixed_Asm_32:
5621 case ARM::VST2LNqWB_fixed_Asm_16:
5622 case ARM::VST2LNqWB_fixed_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005623 MCInst TmpInst;
5624 // Shuffle the operands around so the lane index operand is in the
5625 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005626 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005627 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005628 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5629 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5630 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5631 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5632 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005633 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5634 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005635 TmpInst.addOperand(Inst.getOperand(1)); // lane
5636 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5637 TmpInst.addOperand(Inst.getOperand(5));
5638 Inst = TmpInst;
5639 return true;
5640 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005641
5642 case ARM::VST3LNdWB_fixed_Asm_8:
5643 case ARM::VST3LNdWB_fixed_Asm_16:
5644 case ARM::VST3LNdWB_fixed_Asm_32:
5645 case ARM::VST3LNqWB_fixed_Asm_16:
5646 case ARM::VST3LNqWB_fixed_Asm_32: {
5647 MCInst TmpInst;
5648 // Shuffle the operands around so the lane index operand is in the
5649 // right place.
5650 unsigned Spacing;
5651 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5652 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5653 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5654 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5655 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5656 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5657 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5658 Spacing));
5659 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5660 Spacing * 2));
5661 TmpInst.addOperand(Inst.getOperand(1)); // lane
5662 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5663 TmpInst.addOperand(Inst.getOperand(5));
5664 Inst = TmpInst;
5665 return true;
5666 }
5667
Jim Grosbach88a54de2012-01-24 18:53:13 +00005668 case ARM::VST4LNdWB_fixed_Asm_8:
5669 case ARM::VST4LNdWB_fixed_Asm_16:
5670 case ARM::VST4LNdWB_fixed_Asm_32:
5671 case ARM::VST4LNqWB_fixed_Asm_16:
5672 case ARM::VST4LNqWB_fixed_Asm_32: {
5673 MCInst TmpInst;
5674 // Shuffle the operands around so the lane index operand is in the
5675 // right place.
5676 unsigned Spacing;
5677 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5678 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5679 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5680 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5681 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5682 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5683 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5684 Spacing));
5685 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5686 Spacing * 2));
5687 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5688 Spacing * 3));
5689 TmpInst.addOperand(Inst.getOperand(1)); // lane
5690 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5691 TmpInst.addOperand(Inst.getOperand(5));
5692 Inst = TmpInst;
5693 return true;
5694 }
5695
Jim Grosbach8b31f952012-01-23 19:39:08 +00005696 case ARM::VST1LNdAsm_8:
5697 case ARM::VST1LNdAsm_16:
5698 case ARM::VST1LNdAsm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005699 MCInst TmpInst;
5700 // Shuffle the operands around so the lane index operand is in the
5701 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005702 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005703 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005704 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5705 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5706 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5707 TmpInst.addOperand(Inst.getOperand(1)); // lane
5708 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5709 TmpInst.addOperand(Inst.getOperand(5));
5710 Inst = TmpInst;
5711 return true;
5712 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005713
Jim Grosbach8b31f952012-01-23 19:39:08 +00005714 case ARM::VST2LNdAsm_8:
5715 case ARM::VST2LNdAsm_16:
5716 case ARM::VST2LNdAsm_32:
5717 case ARM::VST2LNqAsm_16:
5718 case ARM::VST2LNqAsm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005719 MCInst TmpInst;
5720 // Shuffle the operands around so the lane index operand is in the
5721 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005722 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005723 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005724 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5725 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5726 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005727 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5728 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005729 TmpInst.addOperand(Inst.getOperand(1)); // lane
5730 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5731 TmpInst.addOperand(Inst.getOperand(5));
5732 Inst = TmpInst;
5733 return true;
5734 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005735
5736 case ARM::VST3LNdAsm_8:
5737 case ARM::VST3LNdAsm_16:
5738 case ARM::VST3LNdAsm_32:
5739 case ARM::VST3LNqAsm_16:
5740 case ARM::VST3LNqAsm_32: {
5741 MCInst TmpInst;
5742 // Shuffle the operands around so the lane index operand is in the
5743 // right place.
5744 unsigned Spacing;
5745 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5746 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5747 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5748 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5749 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5750 Spacing));
5751 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5752 Spacing * 2));
5753 TmpInst.addOperand(Inst.getOperand(1)); // lane
5754 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5755 TmpInst.addOperand(Inst.getOperand(5));
5756 Inst = TmpInst;
5757 return true;
5758 }
5759
Jim Grosbach88a54de2012-01-24 18:53:13 +00005760 case ARM::VST4LNdAsm_8:
5761 case ARM::VST4LNdAsm_16:
5762 case ARM::VST4LNdAsm_32:
5763 case ARM::VST4LNqAsm_16:
5764 case ARM::VST4LNqAsm_32: {
5765 MCInst TmpInst;
5766 // Shuffle the operands around so the lane index operand is in the
5767 // right place.
5768 unsigned Spacing;
5769 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5770 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5771 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5772 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5773 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5774 Spacing));
5775 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5776 Spacing * 2));
5777 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5778 Spacing * 3));
5779 TmpInst.addOperand(Inst.getOperand(1)); // lane
5780 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5781 TmpInst.addOperand(Inst.getOperand(5));
5782 Inst = TmpInst;
5783 return true;
5784 }
5785
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005786 // Handle NEON VLD complex aliases.
Jim Grosbach8b31f952012-01-23 19:39:08 +00005787 case ARM::VLD1LNdWB_register_Asm_8:
5788 case ARM::VLD1LNdWB_register_Asm_16:
5789 case ARM::VLD1LNdWB_register_Asm_32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005790 MCInst TmpInst;
5791 // Shuffle the operands around so the lane index operand is in the
5792 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005793 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005794 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005795 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5796 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5797 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5798 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5799 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5800 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5801 TmpInst.addOperand(Inst.getOperand(1)); // lane
5802 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5803 TmpInst.addOperand(Inst.getOperand(6));
5804 Inst = TmpInst;
5805 return true;
5806 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005807
Jim Grosbach8b31f952012-01-23 19:39:08 +00005808 case ARM::VLD2LNdWB_register_Asm_8:
5809 case ARM::VLD2LNdWB_register_Asm_16:
5810 case ARM::VLD2LNdWB_register_Asm_32:
5811 case ARM::VLD2LNqWB_register_Asm_16:
5812 case ARM::VLD2LNqWB_register_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005813 MCInst TmpInst;
5814 // Shuffle the operands around so the lane index operand is in the
5815 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005816 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005817 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005818 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005819 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5820 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005821 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5822 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5823 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5824 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5825 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005826 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5827 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005828 TmpInst.addOperand(Inst.getOperand(1)); // lane
5829 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5830 TmpInst.addOperand(Inst.getOperand(6));
5831 Inst = TmpInst;
5832 return true;
5833 }
5834
Jim Grosbach3a678af2012-01-23 21:53:26 +00005835 case ARM::VLD3LNdWB_register_Asm_8:
5836 case ARM::VLD3LNdWB_register_Asm_16:
5837 case ARM::VLD3LNdWB_register_Asm_32:
5838 case ARM::VLD3LNqWB_register_Asm_16:
5839 case ARM::VLD3LNqWB_register_Asm_32: {
5840 MCInst TmpInst;
5841 // Shuffle the operands around so the lane index operand is in the
5842 // right place.
5843 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005844 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005845 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5846 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5847 Spacing));
5848 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005849 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005850 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5851 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5852 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5853 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5854 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5855 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5856 Spacing));
5857 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005858 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005859 TmpInst.addOperand(Inst.getOperand(1)); // lane
5860 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5861 TmpInst.addOperand(Inst.getOperand(6));
5862 Inst = TmpInst;
5863 return true;
5864 }
5865
Jim Grosbache983a132012-01-24 18:37:25 +00005866 case ARM::VLD4LNdWB_register_Asm_8:
5867 case ARM::VLD4LNdWB_register_Asm_16:
5868 case ARM::VLD4LNdWB_register_Asm_32:
5869 case ARM::VLD4LNqWB_register_Asm_16:
5870 case ARM::VLD4LNqWB_register_Asm_32: {
5871 MCInst TmpInst;
5872 // Shuffle the operands around so the lane index operand is in the
5873 // right place.
5874 unsigned Spacing;
5875 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
5876 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(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5882 Spacing * 3));
5883 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5884 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5885 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5886 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5887 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5888 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5889 Spacing));
5890 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5891 Spacing * 2));
5892 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5893 Spacing * 3));
5894 TmpInst.addOperand(Inst.getOperand(1)); // lane
5895 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5896 TmpInst.addOperand(Inst.getOperand(6));
5897 Inst = TmpInst;
5898 return true;
5899 }
5900
Jim Grosbach8b31f952012-01-23 19:39:08 +00005901 case ARM::VLD1LNdWB_fixed_Asm_8:
5902 case ARM::VLD1LNdWB_fixed_Asm_16:
5903 case ARM::VLD1LNdWB_fixed_Asm_32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005904 MCInst TmpInst;
5905 // Shuffle the operands around so the lane index operand is in the
5906 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005907 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005908 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005909 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5910 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5911 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5912 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5913 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5914 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5915 TmpInst.addOperand(Inst.getOperand(1)); // lane
5916 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5917 TmpInst.addOperand(Inst.getOperand(5));
5918 Inst = TmpInst;
5919 return true;
5920 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005921
Jim Grosbach8b31f952012-01-23 19:39:08 +00005922 case ARM::VLD2LNdWB_fixed_Asm_8:
5923 case ARM::VLD2LNdWB_fixed_Asm_16:
5924 case ARM::VLD2LNdWB_fixed_Asm_32:
5925 case ARM::VLD2LNqWB_fixed_Asm_16:
5926 case ARM::VLD2LNqWB_fixed_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005927 MCInst TmpInst;
5928 // Shuffle the operands around so the lane index operand is in the
5929 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005930 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005931 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005932 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005933 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5934 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005935 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5936 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5937 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5938 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5939 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005940 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5941 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005942 TmpInst.addOperand(Inst.getOperand(1)); // lane
5943 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5944 TmpInst.addOperand(Inst.getOperand(5));
5945 Inst = TmpInst;
5946 return true;
5947 }
5948
Jim Grosbach3a678af2012-01-23 21:53:26 +00005949 case ARM::VLD3LNdWB_fixed_Asm_8:
5950 case ARM::VLD3LNdWB_fixed_Asm_16:
5951 case ARM::VLD3LNdWB_fixed_Asm_32:
5952 case ARM::VLD3LNqWB_fixed_Asm_16:
5953 case ARM::VLD3LNqWB_fixed_Asm_32: {
5954 MCInst TmpInst;
5955 // Shuffle the operands around so the lane index operand is in the
5956 // right place.
5957 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005958 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005959 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5960 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5961 Spacing));
5962 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005963 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005964 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5965 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5966 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5967 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5968 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5969 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5970 Spacing));
5971 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005972 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005973 TmpInst.addOperand(Inst.getOperand(1)); // lane
5974 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5975 TmpInst.addOperand(Inst.getOperand(5));
5976 Inst = TmpInst;
5977 return true;
5978 }
5979
Jim Grosbache983a132012-01-24 18:37:25 +00005980 case ARM::VLD4LNdWB_fixed_Asm_8:
5981 case ARM::VLD4LNdWB_fixed_Asm_16:
5982 case ARM::VLD4LNdWB_fixed_Asm_32:
5983 case ARM::VLD4LNqWB_fixed_Asm_16:
5984 case ARM::VLD4LNqWB_fixed_Asm_32: {
5985 MCInst TmpInst;
5986 // Shuffle the operands around so the lane index operand is in the
5987 // right place.
5988 unsigned Spacing;
5989 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
5990 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5991 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5992 Spacing));
5993 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5994 Spacing * 2));
5995 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5996 Spacing * 3));
5997 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5998 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5999 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6000 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6001 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6002 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6003 Spacing));
6004 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6005 Spacing * 2));
6006 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6007 Spacing * 3));
6008 TmpInst.addOperand(Inst.getOperand(1)); // lane
6009 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6010 TmpInst.addOperand(Inst.getOperand(5));
6011 Inst = TmpInst;
6012 return true;
6013 }
6014
Jim Grosbach8b31f952012-01-23 19:39:08 +00006015 case ARM::VLD1LNdAsm_8:
6016 case ARM::VLD1LNdAsm_16:
6017 case ARM::VLD1LNdAsm_32: {
Jim Grosbach7636bf62011-12-02 00:35:16 +00006018 MCInst TmpInst;
6019 // Shuffle the operands around so the lane index operand is in the
6020 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006021 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006022 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach7636bf62011-12-02 00:35:16 +00006023 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6024 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6025 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6026 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6027 TmpInst.addOperand(Inst.getOperand(1)); // lane
6028 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6029 TmpInst.addOperand(Inst.getOperand(5));
6030 Inst = TmpInst;
6031 return true;
6032 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006033
Jim Grosbach8b31f952012-01-23 19:39:08 +00006034 case ARM::VLD2LNdAsm_8:
6035 case ARM::VLD2LNdAsm_16:
6036 case ARM::VLD2LNdAsm_32:
6037 case ARM::VLD2LNqAsm_16:
6038 case ARM::VLD2LNqAsm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006039 MCInst TmpInst;
6040 // Shuffle the operands around so the lane index operand is in the
6041 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006042 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006043 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006044 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006045 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6046 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006047 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6048 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6049 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006050 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6051 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006052 TmpInst.addOperand(Inst.getOperand(1)); // lane
6053 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6054 TmpInst.addOperand(Inst.getOperand(5));
6055 Inst = TmpInst;
6056 return true;
6057 }
Jim Grosbach3a678af2012-01-23 21:53:26 +00006058
6059 case ARM::VLD3LNdAsm_8:
6060 case ARM::VLD3LNdAsm_16:
6061 case ARM::VLD3LNdAsm_32:
6062 case ARM::VLD3LNqAsm_16:
6063 case ARM::VLD3LNqAsm_32: {
6064 MCInst TmpInst;
6065 // Shuffle the operands around so the lane index operand is in the
6066 // right place.
6067 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006068 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006069 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6070 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6071 Spacing));
6072 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006073 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006074 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6075 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6076 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6077 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6078 Spacing));
6079 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006080 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006081 TmpInst.addOperand(Inst.getOperand(1)); // lane
6082 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6083 TmpInst.addOperand(Inst.getOperand(5));
6084 Inst = TmpInst;
6085 return true;
6086 }
6087
Jim Grosbache983a132012-01-24 18:37:25 +00006088 case ARM::VLD4LNdAsm_8:
6089 case ARM::VLD4LNdAsm_16:
6090 case ARM::VLD4LNdAsm_32:
6091 case ARM::VLD4LNqAsm_16:
6092 case ARM::VLD4LNqAsm_32: {
6093 MCInst TmpInst;
6094 // Shuffle the operands around so the lane index operand is in the
6095 // right place.
6096 unsigned Spacing;
6097 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6098 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6099 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6100 Spacing));
6101 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6102 Spacing * 2));
6103 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6104 Spacing * 3));
6105 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6106 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6107 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6108 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6109 Spacing));
6110 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6111 Spacing * 2));
6112 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6113 Spacing * 3));
6114 TmpInst.addOperand(Inst.getOperand(1)); // lane
6115 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6116 TmpInst.addOperand(Inst.getOperand(5));
6117 Inst = TmpInst;
6118 return true;
6119 }
6120
Jim Grosbach5e59f7e2012-01-24 23:47:04 +00006121 // VLD3DUP single 3-element structure to all lanes instructions.
6122 case ARM::VLD3DUPdAsm_8:
6123 case ARM::VLD3DUPdAsm_16:
6124 case ARM::VLD3DUPdAsm_32:
6125 case ARM::VLD3DUPqAsm_8:
6126 case ARM::VLD3DUPqAsm_16:
6127 case ARM::VLD3DUPqAsm_32: {
6128 MCInst TmpInst;
6129 unsigned Spacing;
6130 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6131 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6132 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6133 Spacing));
6134 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6135 Spacing * 2));
6136 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6137 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6138 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6139 TmpInst.addOperand(Inst.getOperand(4));
6140 Inst = TmpInst;
6141 return true;
6142 }
6143
6144 case ARM::VLD3DUPdWB_fixed_Asm_8:
6145 case ARM::VLD3DUPdWB_fixed_Asm_16:
6146 case ARM::VLD3DUPdWB_fixed_Asm_32:
6147 case ARM::VLD3DUPqWB_fixed_Asm_8:
6148 case ARM::VLD3DUPqWB_fixed_Asm_16:
6149 case ARM::VLD3DUPqWB_fixed_Asm_32: {
6150 MCInst TmpInst;
6151 unsigned Spacing;
6152 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6153 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6154 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6155 Spacing));
6156 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6157 Spacing * 2));
6158 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6159 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6160 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6161 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6162 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6163 TmpInst.addOperand(Inst.getOperand(4));
6164 Inst = TmpInst;
6165 return true;
6166 }
6167
6168 case ARM::VLD3DUPdWB_register_Asm_8:
6169 case ARM::VLD3DUPdWB_register_Asm_16:
6170 case ARM::VLD3DUPdWB_register_Asm_32:
6171 case ARM::VLD3DUPqWB_register_Asm_8:
6172 case ARM::VLD3DUPqWB_register_Asm_16:
6173 case ARM::VLD3DUPqWB_register_Asm_32: {
6174 MCInst TmpInst;
6175 unsigned Spacing;
6176 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6177 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6178 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6179 Spacing));
6180 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6181 Spacing * 2));
6182 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6183 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6184 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6185 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6186 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6187 TmpInst.addOperand(Inst.getOperand(5));
6188 Inst = TmpInst;
6189 return true;
6190 }
6191
Jim Grosbachc387fc62012-01-23 23:20:46 +00006192 // VLD3 multiple 3-element structure instructions.
6193 case ARM::VLD3dAsm_8:
6194 case ARM::VLD3dAsm_16:
6195 case ARM::VLD3dAsm_32:
6196 case ARM::VLD3qAsm_8:
6197 case ARM::VLD3qAsm_16:
6198 case ARM::VLD3qAsm_32: {
6199 MCInst TmpInst;
6200 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006201 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00006202 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6203 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6204 Spacing));
6205 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6206 Spacing * 2));
6207 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6208 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6209 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6210 TmpInst.addOperand(Inst.getOperand(4));
6211 Inst = TmpInst;
6212 return true;
6213 }
6214
6215 case ARM::VLD3dWB_fixed_Asm_8:
6216 case ARM::VLD3dWB_fixed_Asm_16:
6217 case ARM::VLD3dWB_fixed_Asm_32:
6218 case ARM::VLD3qWB_fixed_Asm_8:
6219 case ARM::VLD3qWB_fixed_Asm_16:
6220 case ARM::VLD3qWB_fixed_Asm_32: {
6221 MCInst TmpInst;
6222 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006223 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00006224 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6225 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6226 Spacing));
6227 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6228 Spacing * 2));
6229 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6230 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6231 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6232 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6233 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6234 TmpInst.addOperand(Inst.getOperand(4));
6235 Inst = TmpInst;
6236 return true;
6237 }
6238
6239 case ARM::VLD3dWB_register_Asm_8:
6240 case ARM::VLD3dWB_register_Asm_16:
6241 case ARM::VLD3dWB_register_Asm_32:
6242 case ARM::VLD3qWB_register_Asm_8:
6243 case ARM::VLD3qWB_register_Asm_16:
6244 case ARM::VLD3qWB_register_Asm_32: {
6245 MCInst TmpInst;
6246 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006247 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00006248 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6249 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6250 Spacing));
6251 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6252 Spacing * 2));
6253 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6254 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6255 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6256 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6257 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6258 TmpInst.addOperand(Inst.getOperand(5));
6259 Inst = TmpInst;
6260 return true;
6261 }
6262
Jim Grosbacha57a36a2012-01-25 00:01:08 +00006263 // VLD4DUP single 3-element structure to all lanes instructions.
6264 case ARM::VLD4DUPdAsm_8:
6265 case ARM::VLD4DUPdAsm_16:
6266 case ARM::VLD4DUPdAsm_32:
6267 case ARM::VLD4DUPqAsm_8:
6268 case ARM::VLD4DUPqAsm_16:
6269 case ARM::VLD4DUPqAsm_32: {
6270 MCInst TmpInst;
6271 unsigned Spacing;
6272 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6273 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6274 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6275 Spacing));
6276 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6277 Spacing * 2));
6278 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6279 Spacing * 3));
6280 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6281 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6282 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6283 TmpInst.addOperand(Inst.getOperand(4));
6284 Inst = TmpInst;
6285 return true;
6286 }
6287
6288 case ARM::VLD4DUPdWB_fixed_Asm_8:
6289 case ARM::VLD4DUPdWB_fixed_Asm_16:
6290 case ARM::VLD4DUPdWB_fixed_Asm_32:
6291 case ARM::VLD4DUPqWB_fixed_Asm_8:
6292 case ARM::VLD4DUPqWB_fixed_Asm_16:
6293 case ARM::VLD4DUPqWB_fixed_Asm_32: {
6294 MCInst TmpInst;
6295 unsigned Spacing;
6296 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6297 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6298 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6299 Spacing));
6300 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6301 Spacing * 2));
6302 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6303 Spacing * 3));
6304 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6305 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6306 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6307 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6308 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6309 TmpInst.addOperand(Inst.getOperand(4));
6310 Inst = TmpInst;
6311 return true;
6312 }
6313
6314 case ARM::VLD4DUPdWB_register_Asm_8:
6315 case ARM::VLD4DUPdWB_register_Asm_16:
6316 case ARM::VLD4DUPdWB_register_Asm_32:
6317 case ARM::VLD4DUPqWB_register_Asm_8:
6318 case ARM::VLD4DUPqWB_register_Asm_16:
6319 case ARM::VLD4DUPqWB_register_Asm_32: {
6320 MCInst TmpInst;
6321 unsigned Spacing;
6322 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6323 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6324 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6325 Spacing));
6326 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6327 Spacing * 2));
6328 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6329 Spacing * 3));
6330 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6331 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6332 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6333 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6334 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6335 TmpInst.addOperand(Inst.getOperand(5));
6336 Inst = TmpInst;
6337 return true;
6338 }
6339
6340 // VLD4 multiple 4-element structure instructions.
Jim Grosbach8abe7e32012-01-24 00:43:17 +00006341 case ARM::VLD4dAsm_8:
6342 case ARM::VLD4dAsm_16:
6343 case ARM::VLD4dAsm_32:
6344 case ARM::VLD4qAsm_8:
6345 case ARM::VLD4qAsm_16:
6346 case ARM::VLD4qAsm_32: {
6347 MCInst TmpInst;
6348 unsigned Spacing;
6349 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6350 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6351 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6352 Spacing));
6353 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6354 Spacing * 2));
6355 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6356 Spacing * 3));
6357 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6358 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6359 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6360 TmpInst.addOperand(Inst.getOperand(4));
6361 Inst = TmpInst;
6362 return true;
6363 }
6364
6365 case ARM::VLD4dWB_fixed_Asm_8:
6366 case ARM::VLD4dWB_fixed_Asm_16:
6367 case ARM::VLD4dWB_fixed_Asm_32:
6368 case ARM::VLD4qWB_fixed_Asm_8:
6369 case ARM::VLD4qWB_fixed_Asm_16:
6370 case ARM::VLD4qWB_fixed_Asm_32: {
6371 MCInst TmpInst;
6372 unsigned Spacing;
6373 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6374 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6375 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6376 Spacing));
6377 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6378 Spacing * 2));
6379 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6380 Spacing * 3));
6381 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6382 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6383 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6384 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6385 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6386 TmpInst.addOperand(Inst.getOperand(4));
6387 Inst = TmpInst;
6388 return true;
6389 }
6390
6391 case ARM::VLD4dWB_register_Asm_8:
6392 case ARM::VLD4dWB_register_Asm_16:
6393 case ARM::VLD4dWB_register_Asm_32:
6394 case ARM::VLD4qWB_register_Asm_8:
6395 case ARM::VLD4qWB_register_Asm_16:
6396 case ARM::VLD4qWB_register_Asm_32: {
6397 MCInst TmpInst;
6398 unsigned Spacing;
6399 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6400 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6401 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6402 Spacing));
6403 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6404 Spacing * 2));
6405 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6406 Spacing * 3));
6407 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6408 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6409 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6410 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6411 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6412 TmpInst.addOperand(Inst.getOperand(5));
6413 Inst = TmpInst;
6414 return true;
6415 }
6416
Jim Grosbachd7433e22012-01-23 23:45:44 +00006417 // VST3 multiple 3-element structure instructions.
6418 case ARM::VST3dAsm_8:
6419 case ARM::VST3dAsm_16:
6420 case ARM::VST3dAsm_32:
6421 case ARM::VST3qAsm_8:
6422 case ARM::VST3qAsm_16:
6423 case ARM::VST3qAsm_32: {
6424 MCInst TmpInst;
6425 unsigned Spacing;
6426 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6427 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6428 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6429 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6430 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6431 Spacing));
6432 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6433 Spacing * 2));
6434 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6435 TmpInst.addOperand(Inst.getOperand(4));
6436 Inst = TmpInst;
6437 return true;
6438 }
6439
6440 case ARM::VST3dWB_fixed_Asm_8:
6441 case ARM::VST3dWB_fixed_Asm_16:
6442 case ARM::VST3dWB_fixed_Asm_32:
6443 case ARM::VST3qWB_fixed_Asm_8:
6444 case ARM::VST3qWB_fixed_Asm_16:
6445 case ARM::VST3qWB_fixed_Asm_32: {
6446 MCInst TmpInst;
6447 unsigned Spacing;
6448 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6449 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6450 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6451 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6452 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6453 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6454 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6455 Spacing));
6456 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6457 Spacing * 2));
6458 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6459 TmpInst.addOperand(Inst.getOperand(4));
6460 Inst = TmpInst;
6461 return true;
6462 }
6463
6464 case ARM::VST3dWB_register_Asm_8:
6465 case ARM::VST3dWB_register_Asm_16:
6466 case ARM::VST3dWB_register_Asm_32:
6467 case ARM::VST3qWB_register_Asm_8:
6468 case ARM::VST3qWB_register_Asm_16:
6469 case ARM::VST3qWB_register_Asm_32: {
6470 MCInst TmpInst;
6471 unsigned Spacing;
6472 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6473 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6474 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6475 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6476 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6477 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6478 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6479 Spacing));
6480 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6481 Spacing * 2));
6482 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6483 TmpInst.addOperand(Inst.getOperand(5));
6484 Inst = TmpInst;
6485 return true;
6486 }
6487
Jim Grosbach539aab72012-01-24 00:58:13 +00006488 // VST4 multiple 3-element structure instructions.
6489 case ARM::VST4dAsm_8:
6490 case ARM::VST4dAsm_16:
6491 case ARM::VST4dAsm_32:
6492 case ARM::VST4qAsm_8:
6493 case ARM::VST4qAsm_16:
6494 case ARM::VST4qAsm_32: {
6495 MCInst TmpInst;
6496 unsigned Spacing;
6497 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6498 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6499 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6500 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6501 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6502 Spacing));
6503 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6504 Spacing * 2));
6505 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6506 Spacing * 3));
6507 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6508 TmpInst.addOperand(Inst.getOperand(4));
6509 Inst = TmpInst;
6510 return true;
6511 }
6512
6513 case ARM::VST4dWB_fixed_Asm_8:
6514 case ARM::VST4dWB_fixed_Asm_16:
6515 case ARM::VST4dWB_fixed_Asm_32:
6516 case ARM::VST4qWB_fixed_Asm_8:
6517 case ARM::VST4qWB_fixed_Asm_16:
6518 case ARM::VST4qWB_fixed_Asm_32: {
6519 MCInst TmpInst;
6520 unsigned Spacing;
6521 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6522 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6523 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6524 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6525 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6526 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6527 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6528 Spacing));
6529 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6530 Spacing * 2));
6531 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6532 Spacing * 3));
6533 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6534 TmpInst.addOperand(Inst.getOperand(4));
6535 Inst = TmpInst;
6536 return true;
6537 }
6538
6539 case ARM::VST4dWB_register_Asm_8:
6540 case ARM::VST4dWB_register_Asm_16:
6541 case ARM::VST4dWB_register_Asm_32:
6542 case ARM::VST4qWB_register_Asm_8:
6543 case ARM::VST4qWB_register_Asm_16:
6544 case ARM::VST4qWB_register_Asm_32: {
6545 MCInst TmpInst;
6546 unsigned Spacing;
6547 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6548 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6549 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6550 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6551 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6552 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6553 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6554 Spacing));
6555 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6556 Spacing * 2));
6557 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6558 Spacing * 3));
6559 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6560 TmpInst.addOperand(Inst.getOperand(5));
6561 Inst = TmpInst;
6562 return true;
6563 }
6564
Jim Grosbach863d2af2011-12-13 22:45:11 +00006565 // Handle the Thumb2 mode MOV complex aliases.
Jim Grosbach2cc5cda2011-12-21 20:54:00 +00006566 case ARM::t2MOVsr:
6567 case ARM::t2MOVSsr: {
6568 // Which instruction to expand to depends on the CCOut operand and
6569 // whether we're in an IT block if the register operands are low
6570 // registers.
6571 bool isNarrow = false;
6572 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6573 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6574 isARMLowRegister(Inst.getOperand(2).getReg()) &&
6575 Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
6576 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsr))
6577 isNarrow = true;
6578 MCInst TmpInst;
6579 unsigned newOpc;
6580 switch(ARM_AM::getSORegShOp(Inst.getOperand(3).getImm())) {
6581 default: llvm_unreachable("unexpected opcode!");
6582 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRrr : ARM::t2ASRrr; break;
6583 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRrr : ARM::t2LSRrr; break;
6584 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLrr : ARM::t2LSLrr; break;
6585 case ARM_AM::ror: newOpc = isNarrow ? ARM::tROR : ARM::t2RORrr; break;
6586 }
6587 TmpInst.setOpcode(newOpc);
6588 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6589 if (isNarrow)
6590 TmpInst.addOperand(MCOperand::CreateReg(
6591 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6592 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6593 TmpInst.addOperand(Inst.getOperand(2)); // Rm
6594 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6595 TmpInst.addOperand(Inst.getOperand(5));
6596 if (!isNarrow)
6597 TmpInst.addOperand(MCOperand::CreateReg(
6598 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6599 Inst = TmpInst;
6600 return true;
6601 }
Jim Grosbach863d2af2011-12-13 22:45:11 +00006602 case ARM::t2MOVsi:
6603 case ARM::t2MOVSsi: {
6604 // Which instruction to expand to depends on the CCOut operand and
6605 // whether we're in an IT block if the register operands are low
6606 // registers.
6607 bool isNarrow = false;
6608 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6609 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6610 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
6611 isNarrow = true;
6612 MCInst TmpInst;
6613 unsigned newOpc;
6614 switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
6615 default: llvm_unreachable("unexpected opcode!");
6616 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
6617 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
6618 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
6619 case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
Jim Grosbach520dc782011-12-21 21:04:19 +00006620 case ARM_AM::rrx: isNarrow = false; newOpc = ARM::t2RRX; break;
Jim Grosbach863d2af2011-12-13 22:45:11 +00006621 }
6622 unsigned Ammount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
6623 if (Ammount == 32) Ammount = 0;
6624 TmpInst.setOpcode(newOpc);
6625 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6626 if (isNarrow)
6627 TmpInst.addOperand(MCOperand::CreateReg(
6628 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6629 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbach520dc782011-12-21 21:04:19 +00006630 if (newOpc != ARM::t2RRX)
6631 TmpInst.addOperand(MCOperand::CreateImm(Ammount));
Jim Grosbach863d2af2011-12-13 22:45:11 +00006632 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6633 TmpInst.addOperand(Inst.getOperand(4));
6634 if (!isNarrow)
6635 TmpInst.addOperand(MCOperand::CreateReg(
6636 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6637 Inst = TmpInst;
6638 return true;
6639 }
6640 // Handle the ARM mode MOV complex aliases.
Jim Grosbach23f22072011-11-16 18:31:45 +00006641 case ARM::ASRr:
6642 case ARM::LSRr:
6643 case ARM::LSLr:
6644 case ARM::RORr: {
6645 ARM_AM::ShiftOpc ShiftTy;
6646 switch(Inst.getOpcode()) {
6647 default: llvm_unreachable("unexpected opcode!");
6648 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
6649 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
6650 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
6651 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
6652 }
Jim Grosbach23f22072011-11-16 18:31:45 +00006653 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
6654 MCInst TmpInst;
6655 TmpInst.setOpcode(ARM::MOVsr);
6656 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6657 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6658 TmpInst.addOperand(Inst.getOperand(2)); // Rm
6659 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6660 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6661 TmpInst.addOperand(Inst.getOperand(4));
6662 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6663 Inst = TmpInst;
6664 return true;
6665 }
Jim Grosbachee10ff82011-11-10 19:18:01 +00006666 case ARM::ASRi:
6667 case ARM::LSRi:
6668 case ARM::LSLi:
6669 case ARM::RORi: {
6670 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachee10ff82011-11-10 19:18:01 +00006671 switch(Inst.getOpcode()) {
6672 default: llvm_unreachable("unexpected opcode!");
6673 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
6674 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
6675 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
6676 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
6677 }
6678 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach48b368b2011-11-16 19:05:59 +00006679 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachee10ff82011-11-10 19:18:01 +00006680 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
6681 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach71810ab2011-11-10 16:44:55 +00006682 MCInst TmpInst;
Jim Grosbachee10ff82011-11-10 19:18:01 +00006683 TmpInst.setOpcode(Opc);
Jim Grosbach71810ab2011-11-10 16:44:55 +00006684 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6685 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachee10ff82011-11-10 19:18:01 +00006686 if (Opc == ARM::MOVsi)
6687 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach71810ab2011-11-10 16:44:55 +00006688 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6689 TmpInst.addOperand(Inst.getOperand(4));
6690 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6691 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006692 return true;
Jim Grosbach71810ab2011-11-10 16:44:55 +00006693 }
Jim Grosbach48b368b2011-11-16 19:05:59 +00006694 case ARM::RRXi: {
6695 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
6696 MCInst TmpInst;
6697 TmpInst.setOpcode(ARM::MOVsi);
6698 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6699 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6700 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6701 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6702 TmpInst.addOperand(Inst.getOperand(3));
6703 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
6704 Inst = TmpInst;
6705 return true;
6706 }
Jim Grosbach0352b462011-11-10 23:58:34 +00006707 case ARM::t2LDMIA_UPD: {
6708 // If this is a load of a single register, then we should use
6709 // a post-indexed LDR instruction instead, per the ARM ARM.
6710 if (Inst.getNumOperands() != 5)
6711 return false;
6712 MCInst TmpInst;
6713 TmpInst.setOpcode(ARM::t2LDR_POST);
6714 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6715 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6716 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6717 TmpInst.addOperand(MCOperand::CreateImm(4));
6718 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6719 TmpInst.addOperand(Inst.getOperand(3));
6720 Inst = TmpInst;
6721 return true;
6722 }
6723 case ARM::t2STMDB_UPD: {
6724 // If this is a store of a single register, then we should use
6725 // a pre-indexed STR instruction instead, per the ARM ARM.
6726 if (Inst.getNumOperands() != 5)
6727 return false;
6728 MCInst TmpInst;
6729 TmpInst.setOpcode(ARM::t2STR_PRE);
6730 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6731 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6732 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6733 TmpInst.addOperand(MCOperand::CreateImm(-4));
6734 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6735 TmpInst.addOperand(Inst.getOperand(3));
6736 Inst = TmpInst;
6737 return true;
6738 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00006739 case ARM::LDMIA_UPD:
6740 // If this is a load of a single register via a 'pop', then we should use
6741 // a post-indexed LDR instruction instead, per the ARM ARM.
6742 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
6743 Inst.getNumOperands() == 5) {
6744 MCInst TmpInst;
6745 TmpInst.setOpcode(ARM::LDR_POST_IMM);
6746 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6747 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6748 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6749 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
6750 TmpInst.addOperand(MCOperand::CreateImm(4));
6751 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6752 TmpInst.addOperand(Inst.getOperand(3));
6753 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006754 return true;
Jim Grosbachf8fce712011-08-11 17:35:48 +00006755 }
6756 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00006757 case ARM::STMDB_UPD:
6758 // If this is a store of a single register via a 'push', then we should use
6759 // a pre-indexed STR instruction instead, per the ARM ARM.
6760 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
6761 Inst.getNumOperands() == 5) {
6762 MCInst TmpInst;
6763 TmpInst.setOpcode(ARM::STR_PRE_IMM);
6764 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6765 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6766 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
6767 TmpInst.addOperand(MCOperand::CreateImm(-4));
6768 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6769 TmpInst.addOperand(Inst.getOperand(3));
6770 Inst = TmpInst;
6771 }
6772 break;
Jim Grosbachda847862011-12-05 21:06:26 +00006773 case ARM::t2ADDri12:
6774 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
6775 // mnemonic was used (not "addw"), encoding T3 is preferred.
6776 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
6777 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
6778 break;
6779 Inst.setOpcode(ARM::t2ADDri);
6780 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
6781 break;
6782 case ARM::t2SUBri12:
6783 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
6784 // mnemonic was used (not "subw"), encoding T3 is preferred.
6785 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
6786 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
6787 break;
6788 Inst.setOpcode(ARM::t2SUBri);
6789 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
6790 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006791 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00006792 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6793 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6794 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6795 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00006796 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006797 Inst.setOpcode(ARM::tADDi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006798 return true;
6799 }
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006800 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00006801 case ARM::tSUBi8:
6802 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6803 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6804 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6805 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00006806 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachf67e8552011-09-16 22:58:42 +00006807 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006808 return true;
6809 }
Jim Grosbachf67e8552011-09-16 22:58:42 +00006810 break;
Jim Grosbach927b9df2011-12-05 22:16:39 +00006811 case ARM::t2ADDrr: {
6812 // If the destination and first source operand are the same, and
6813 // there's no setting of the flags, use encoding T2 instead of T3.
6814 // Note that this is only for ADD, not SUB. This mirrors the system
6815 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
6816 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
6817 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbach713c7022011-12-05 22:27:04 +00006818 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6819 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbach927b9df2011-12-05 22:16:39 +00006820 break;
6821 MCInst TmpInst;
6822 TmpInst.setOpcode(ARM::tADDhirr);
6823 TmpInst.addOperand(Inst.getOperand(0));
6824 TmpInst.addOperand(Inst.getOperand(0));
6825 TmpInst.addOperand(Inst.getOperand(2));
6826 TmpInst.addOperand(Inst.getOperand(3));
6827 TmpInst.addOperand(Inst.getOperand(4));
6828 Inst = TmpInst;
6829 return true;
6830 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006831 case ARM::tB:
6832 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006833 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006834 Inst.setOpcode(ARM::tBcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006835 return true;
6836 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006837 break;
6838 case ARM::t2B:
6839 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006840 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006841 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006842 return true;
6843 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006844 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00006845 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00006846 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006847 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbachc0755102011-08-31 21:17:31 +00006848 Inst.setOpcode(ARM::t2B);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006849 return true;
6850 }
Jim Grosbachc0755102011-08-31 21:17:31 +00006851 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00006852 case ARM::tBcc:
6853 // If the conditional is AL, we really want tB.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006854 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbach395b4532011-08-17 22:57:40 +00006855 Inst.setOpcode(ARM::tB);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006856 return true;
6857 }
Jim Grosbach3ce23d32011-08-18 16:08:39 +00006858 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00006859 case ARM::tLDMIA: {
6860 // If the register list contains any high registers, or if the writeback
6861 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
6862 // instead if we're in Thumb2. Otherwise, this should have generated
6863 // an error in validateInstruction().
6864 unsigned Rn = Inst.getOperand(0).getReg();
6865 bool hasWritebackToken =
6866 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6867 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
6868 bool listContainsBase;
6869 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
6870 (!listContainsBase && !hasWritebackToken) ||
6871 (listContainsBase && hasWritebackToken)) {
6872 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6873 assert (isThumbTwo());
6874 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
6875 // If we're switching to the updating version, we need to insert
6876 // the writeback tied operand.
6877 if (hasWritebackToken)
6878 Inst.insert(Inst.begin(),
6879 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006880 return true;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00006881 }
6882 break;
6883 }
Jim Grosbach8213c962011-09-16 20:50:13 +00006884 case ARM::tSTMIA_UPD: {
6885 // If the register list contains any high registers, we need to use
6886 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6887 // should have generated an error in validateInstruction().
6888 unsigned Rn = Inst.getOperand(0).getReg();
6889 bool listContainsBase;
6890 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
6891 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6892 assert (isThumbTwo());
6893 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006894 return true;
Jim Grosbach8213c962011-09-16 20:50:13 +00006895 }
6896 break;
6897 }
Jim Grosbach54026372011-11-10 23:17:11 +00006898 case ARM::tPOP: {
6899 bool listContainsBase;
6900 // If the register list contains any high registers, we need to use
6901 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6902 // should have generated an error in validateInstruction().
6903 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00006904 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00006905 assert (isThumbTwo());
6906 Inst.setOpcode(ARM::t2LDMIA_UPD);
6907 // Add the base register and writeback operands.
6908 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6909 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006910 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00006911 }
6912 case ARM::tPUSH: {
6913 bool listContainsBase;
6914 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00006915 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00006916 assert (isThumbTwo());
6917 Inst.setOpcode(ARM::t2STMDB_UPD);
6918 // Add the base register and writeback operands.
6919 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6920 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006921 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00006922 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006923 case ARM::t2MOVi: {
6924 // If we can use the 16-bit encoding and the user didn't explicitly
6925 // request the 32-bit variant, transform it here.
6926 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6927 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00006928 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
6929 Inst.getOperand(4).getReg() == ARM::CPSR) ||
6930 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006931 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6932 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6933 // The operands aren't in the same order for tMOVi8...
6934 MCInst TmpInst;
6935 TmpInst.setOpcode(ARM::tMOVi8);
6936 TmpInst.addOperand(Inst.getOperand(0));
6937 TmpInst.addOperand(Inst.getOperand(4));
6938 TmpInst.addOperand(Inst.getOperand(1));
6939 TmpInst.addOperand(Inst.getOperand(2));
6940 TmpInst.addOperand(Inst.getOperand(3));
6941 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006942 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006943 }
6944 break;
6945 }
6946 case ARM::t2MOVr: {
6947 // If we can use the 16-bit encoding and the user didn't explicitly
6948 // request the 32-bit variant, transform it here.
6949 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6950 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6951 Inst.getOperand(2).getImm() == ARMCC::AL &&
6952 Inst.getOperand(4).getReg() == ARM::CPSR &&
6953 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6954 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6955 // The operands aren't the same for tMOV[S]r... (no cc_out)
6956 MCInst TmpInst;
6957 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
6958 TmpInst.addOperand(Inst.getOperand(0));
6959 TmpInst.addOperand(Inst.getOperand(1));
6960 TmpInst.addOperand(Inst.getOperand(2));
6961 TmpInst.addOperand(Inst.getOperand(3));
6962 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006963 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006964 }
6965 break;
6966 }
Jim Grosbach326efe52011-09-19 20:29:33 +00006967 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00006968 case ARM::t2SXTB:
6969 case ARM::t2UXTH:
6970 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00006971 // If we can use the 16-bit encoding and the user didn't explicitly
6972 // request the 32-bit variant, transform it here.
6973 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6974 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6975 Inst.getOperand(2).getImm() == 0 &&
6976 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6977 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00006978 unsigned NewOpc;
6979 switch (Inst.getOpcode()) {
6980 default: llvm_unreachable("Illegal opcode!");
6981 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
6982 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
6983 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
6984 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
6985 }
Jim Grosbach326efe52011-09-19 20:29:33 +00006986 // The operands aren't the same for thumb1 (no rotate operand).
6987 MCInst TmpInst;
6988 TmpInst.setOpcode(NewOpc);
6989 TmpInst.addOperand(Inst.getOperand(0));
6990 TmpInst.addOperand(Inst.getOperand(1));
6991 TmpInst.addOperand(Inst.getOperand(3));
6992 TmpInst.addOperand(Inst.getOperand(4));
6993 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006994 return true;
Jim Grosbach326efe52011-09-19 20:29:33 +00006995 }
6996 break;
6997 }
Jim Grosbach04b5d932011-12-20 00:59:38 +00006998 case ARM::MOVsi: {
6999 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm());
7000 if (SOpc == ARM_AM::rrx) return false;
7001 if (ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()) == 0) {
7002 // Shifting by zero is accepted as a vanilla 'MOVr'
7003 MCInst TmpInst;
7004 TmpInst.setOpcode(ARM::MOVr);
7005 TmpInst.addOperand(Inst.getOperand(0));
7006 TmpInst.addOperand(Inst.getOperand(1));
7007 TmpInst.addOperand(Inst.getOperand(3));
7008 TmpInst.addOperand(Inst.getOperand(4));
7009 TmpInst.addOperand(Inst.getOperand(5));
7010 Inst = TmpInst;
7011 return true;
7012 }
7013 return false;
7014 }
Jim Grosbach8d9550b2011-12-22 18:04:04 +00007015 case ARM::ANDrsi:
7016 case ARM::ORRrsi:
7017 case ARM::EORrsi:
7018 case ARM::BICrsi:
7019 case ARM::SUBrsi:
7020 case ARM::ADDrsi: {
7021 unsigned newOpc;
7022 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(3).getImm());
7023 if (SOpc == ARM_AM::rrx) return false;
7024 switch (Inst.getOpcode()) {
Matt Beaumont-Gay19055cc2012-01-03 19:03:59 +00007025 default: assert(0 && "unexpected opcode!");
Jim Grosbach8d9550b2011-12-22 18:04:04 +00007026 case ARM::ANDrsi: newOpc = ARM::ANDrr; break;
7027 case ARM::ORRrsi: newOpc = ARM::ORRrr; break;
7028 case ARM::EORrsi: newOpc = ARM::EORrr; break;
7029 case ARM::BICrsi: newOpc = ARM::BICrr; break;
7030 case ARM::SUBrsi: newOpc = ARM::SUBrr; break;
7031 case ARM::ADDrsi: newOpc = ARM::ADDrr; break;
7032 }
7033 // If the shift is by zero, use the non-shifted instruction definition.
7034 if (ARM_AM::getSORegOffset(Inst.getOperand(3).getImm()) == 0) {
7035 MCInst TmpInst;
7036 TmpInst.setOpcode(newOpc);
7037 TmpInst.addOperand(Inst.getOperand(0));
7038 TmpInst.addOperand(Inst.getOperand(1));
7039 TmpInst.addOperand(Inst.getOperand(2));
7040 TmpInst.addOperand(Inst.getOperand(4));
7041 TmpInst.addOperand(Inst.getOperand(5));
7042 TmpInst.addOperand(Inst.getOperand(6));
7043 Inst = TmpInst;
7044 return true;
7045 }
7046 return false;
7047 }
Jim Grosbach74423e32012-01-25 19:52:01 +00007048 case ARM::ITasm:
Jim Grosbach89df9962011-08-26 21:43:41 +00007049 case ARM::t2IT: {
7050 // The mask bits for all but the first condition are represented as
7051 // the low bit of the condition code value implies 't'. We currently
7052 // always have 1 implies 't', so XOR toggle the bits if the low bit
7053 // of the condition code is zero. The encoding also expects the low
7054 // bit of the condition to be encoded as bit 4 of the mask operand,
7055 // so mask that in if needed
7056 MCOperand &MO = Inst.getOperand(1);
7057 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007058 unsigned OrigMask = Mask;
7059 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00007060 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00007061 assert(Mask && TZ <= 3 && "illegal IT mask value!");
7062 for (unsigned i = 3; i != TZ; --i)
7063 Mask ^= 1 << i;
7064 } else
7065 Mask |= 0x10;
7066 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007067
7068 // Set up the IT block state according to the IT instruction we just
7069 // matched.
7070 assert(!inITBlock() && "nested IT blocks?!");
7071 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
7072 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
7073 ITState.CurPosition = 0;
7074 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00007075 break;
7076 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00007077 }
Jim Grosbach83ec8772011-11-10 23:42:14 +00007078 return false;
Jim Grosbachf8fce712011-08-11 17:35:48 +00007079}
7080
Jim Grosbach47a0d522011-08-16 20:45:50 +00007081unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
7082 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
7083 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00007084 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00007085 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00007086 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
7087 assert(MCID.hasOptionalDef() &&
7088 "optionally flag setting instruction missing optional def operand");
7089 assert(MCID.NumOperands == Inst.getNumOperands() &&
7090 "operand count mismatch!");
7091 // Find the optional-def operand (cc_out).
7092 unsigned OpNo;
7093 for (OpNo = 0;
7094 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
7095 ++OpNo)
7096 ;
7097 // If we're parsing Thumb1, reject it completely.
7098 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
7099 return Match_MnemonicFail;
7100 // If we're parsing Thumb2, which form is legal depends on whether we're
7101 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007102 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
7103 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00007104 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007105 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
7106 inITBlock())
7107 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00007108 }
Jim Grosbach194bd892011-08-16 22:20:01 +00007109 // Some high-register supporting Thumb1 encodings only allow both registers
7110 // to be from r0-r7 when in Thumb2.
7111 else if (Opc == ARM::tADDhirr && isThumbOne() &&
7112 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7113 isARMLowRegister(Inst.getOperand(2).getReg()))
7114 return Match_RequiresThumb2;
7115 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00007116 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00007117 isARMLowRegister(Inst.getOperand(0).getReg()) &&
7118 isARMLowRegister(Inst.getOperand(1).getReg()))
7119 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00007120 return Match_Success;
7121}
7122
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007123bool ARMAsmParser::
7124MatchAndEmitInstruction(SMLoc IDLoc,
7125 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
7126 MCStreamer &Out) {
7127 MCInst Inst;
7128 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00007129 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00007130 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00007131 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00007132 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00007133 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00007134 // Context sensitive operand constraints aren't handled by the matcher,
7135 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00007136 if (validateInstruction(Inst, Operands)) {
7137 // Still progress the IT block, otherwise one wrong condition causes
7138 // nasty cascading errors.
7139 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00007140 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00007141 }
Jim Grosbach189610f2011-07-26 18:25:39 +00007142
Jim Grosbachf8fce712011-08-11 17:35:48 +00007143 // Some instructions need post-processing to, for example, tweak which
Jim Grosbach83ec8772011-11-10 23:42:14 +00007144 // encoding is selected. Loop on it while changes happen so the
7145 // individual transformations can chain off each other. E.g.,
7146 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
7147 while (processInstruction(Inst, Operands))
7148 ;
Jim Grosbachf8fce712011-08-11 17:35:48 +00007149
Jim Grosbacha1109882011-09-02 23:22:08 +00007150 // Only move forward at the very end so that everything in validate
7151 // and process gets a consistent answer about whether we're in an IT
7152 // block.
7153 forwardITPosition();
7154
Jim Grosbach74423e32012-01-25 19:52:01 +00007155 // ITasm is an ARM mode pseudo-instruction that just sets the ITblock and
7156 // doesn't actually encode.
7157 if (Inst.getOpcode() == ARM::ITasm)
7158 return false;
7159
Jim Grosbach42e6bd32012-01-26 23:20:15 +00007160 Inst.setLoc(IDLoc);
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007161 Out.EmitInstruction(Inst);
7162 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00007163 case Match_MissingFeature:
7164 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
7165 return true;
7166 case Match_InvalidOperand: {
7167 SMLoc ErrorLoc = IDLoc;
7168 if (ErrorInfo != ~0U) {
7169 if (ErrorInfo >= Operands.size())
7170 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00007171
Chris Lattnere73d4f82010-10-28 21:41:58 +00007172 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
7173 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
7174 }
Jim Grosbach16c74252010-10-29 14:46:02 +00007175
Chris Lattnere73d4f82010-10-28 21:41:58 +00007176 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007177 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00007178 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00007179 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00007180 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00007181 // The converter function will have already emited a diagnostic.
7182 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007183 case Match_RequiresNotITBlock:
7184 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00007185 case Match_RequiresITBlock:
7186 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00007187 case Match_RequiresV6:
7188 return Error(IDLoc, "instruction variant requires ARMv6 or later");
7189 case Match_RequiresThumb2:
7190 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00007191 }
Jim Grosbach16c74252010-10-29 14:46:02 +00007192
Eric Christopherc223e2b2010-10-29 09:26:59 +00007193 llvm_unreachable("Implement any new match types added!");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007194}
7195
Jim Grosbach1355cf12011-07-26 17:10:22 +00007196/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007197bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
7198 StringRef IDVal = DirectiveID.getIdentifier();
7199 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007200 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007201 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007202 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach9a70df92011-12-07 18:04:19 +00007203 else if (IDVal == ".arm")
7204 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007205 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007206 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007207 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007208 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007209 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007210 return parseDirectiveSyntax(DirectiveID.getLoc());
Jim Grosbacha39cda72011-12-14 02:16:11 +00007211 else if (IDVal == ".unreq")
7212 return parseDirectiveUnreq(DirectiveID.getLoc());
Jason W Kimd7c9e082011-12-20 17:38:12 +00007213 else if (IDVal == ".arch")
7214 return parseDirectiveArch(DirectiveID.getLoc());
7215 else if (IDVal == ".eabi_attribute")
7216 return parseDirectiveEabiAttr(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007217 return true;
7218}
7219
Jim Grosbach1355cf12011-07-26 17:10:22 +00007220/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007221/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00007222bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007223 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7224 for (;;) {
7225 const MCExpr *Value;
7226 if (getParser().ParseExpression(Value))
7227 return true;
7228
Chris Lattneraaec2052010-01-19 19:46:13 +00007229 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007230
7231 if (getLexer().is(AsmToken::EndOfStatement))
7232 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00007233
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007234 // FIXME: Improve diagnostic.
7235 if (getLexer().isNot(AsmToken::Comma))
7236 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007237 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007238 }
7239 }
7240
Sean Callananb9a25b72010-01-19 20:27:46 +00007241 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007242 return false;
7243}
7244
Jim Grosbach1355cf12011-07-26 17:10:22 +00007245/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00007246/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00007247bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00007248 if (getLexer().isNot(AsmToken::EndOfStatement))
7249 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007250 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007251
Jim Grosbach9a70df92011-12-07 18:04:19 +00007252 if (!isThumb())
7253 SwitchMode();
7254 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
7255 return false;
7256}
7257
7258/// parseDirectiveARM
7259/// ::= .arm
7260bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
7261 if (getLexer().isNot(AsmToken::EndOfStatement))
7262 return Error(L, "unexpected token in directive");
7263 Parser.Lex();
7264
7265 if (isThumb())
7266 SwitchMode();
7267 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby515d5092009-10-15 20:48:48 +00007268 return false;
7269}
7270
Jim Grosbach1355cf12011-07-26 17:10:22 +00007271/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00007272/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00007273bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00007274 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
7275 bool isMachO = MAI.hasSubsectionsViaSymbols();
7276 StringRef Name;
Jim Grosbachde4d8392011-12-21 22:30:16 +00007277 bool needFuncName = true;
Rafael Espindola64695402011-05-16 16:17:21 +00007278
Jim Grosbachde4d8392011-12-21 22:30:16 +00007279 // Darwin asm has (optionally) function name after .thumb_func direction
Rafael Espindola64695402011-05-16 16:17:21 +00007280 // ELF doesn't
7281 if (isMachO) {
7282 const AsmToken &Tok = Parser.getTok();
Jim Grosbachde4d8392011-12-21 22:30:16 +00007283 if (Tok.isNot(AsmToken::EndOfStatement)) {
7284 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
7285 return Error(L, "unexpected token in .thumb_func directive");
7286 Name = Tok.getIdentifier();
7287 Parser.Lex(); // Consume the identifier token.
7288 needFuncName = false;
7289 }
Rafael Espindola64695402011-05-16 16:17:21 +00007290 }
7291
Jim Grosbachde4d8392011-12-21 22:30:16 +00007292 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby515d5092009-10-15 20:48:48 +00007293 return Error(L, "unexpected token in directive");
Jim Grosbachde4d8392011-12-21 22:30:16 +00007294
7295 // Eat the end of statement and any blank lines that follow.
7296 while (getLexer().is(AsmToken::EndOfStatement))
7297 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007298
Rafael Espindola64695402011-05-16 16:17:21 +00007299 // FIXME: assuming function name will be the line following .thumb_func
Jim Grosbachde4d8392011-12-21 22:30:16 +00007300 // We really should be checking the next symbol definition even if there's
7301 // stuff in between.
7302 if (needFuncName) {
Jim Grosbachd475f862011-11-10 20:48:53 +00007303 Name = Parser.getTok().getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00007304 }
7305
Jim Grosbach642fc9c2010-11-05 22:33:53 +00007306 // Mark symbol as a thumb symbol.
7307 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
7308 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00007309 return false;
7310}
7311
Jim Grosbach1355cf12011-07-26 17:10:22 +00007312/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00007313/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00007314bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00007315 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00007316 if (Tok.isNot(AsmToken::Identifier))
7317 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00007318 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00007319 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00007320 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00007321 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00007322 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00007323 else
7324 return Error(L, "unrecognized syntax mode in .syntax directive");
7325
7326 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00007327 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007328 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007329
7330 // TODO tell the MC streamer the mode
7331 // getParser().getStreamer().Emit???();
7332 return false;
7333}
7334
Jim Grosbach1355cf12011-07-26 17:10:22 +00007335/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00007336/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00007337bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00007338 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00007339 if (Tok.isNot(AsmToken::Integer))
7340 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00007341 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00007342 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00007343 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00007344 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00007345 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007346 else
7347 return Error(L, "invalid operand to .code directive");
7348
7349 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00007350 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007351 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007352
Evan Cheng32869202011-07-08 22:36:29 +00007353 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00007354 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00007355 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00007356 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00007357 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00007358 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00007359 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00007360 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00007361 }
Jim Grosbach2a301702010-11-05 22:40:53 +00007362
Kevin Enderby515d5092009-10-15 20:48:48 +00007363 return false;
7364}
7365
Jim Grosbacha39cda72011-12-14 02:16:11 +00007366/// parseDirectiveReq
7367/// ::= name .req registername
7368bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
7369 Parser.Lex(); // Eat the '.req' token.
7370 unsigned Reg;
7371 SMLoc SRegLoc, ERegLoc;
7372 if (ParseRegister(Reg, SRegLoc, ERegLoc)) {
7373 Parser.EatToEndOfStatement();
7374 return Error(SRegLoc, "register name expected");
7375 }
7376
7377 // Shouldn't be anything else.
7378 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
7379 Parser.EatToEndOfStatement();
7380 return Error(Parser.getTok().getLoc(),
7381 "unexpected input in .req directive.");
7382 }
7383
7384 Parser.Lex(); // Consume the EndOfStatement
7385
7386 if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg)
7387 return Error(SRegLoc, "redefinition of '" + Name +
7388 "' does not match original.");
7389
7390 return false;
7391}
7392
7393/// parseDirectiveUneq
7394/// ::= .unreq registername
7395bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
7396 if (Parser.getTok().isNot(AsmToken::Identifier)) {
7397 Parser.EatToEndOfStatement();
7398 return Error(L, "unexpected input in .unreq directive.");
7399 }
7400 RegisterReqs.erase(Parser.getTok().getIdentifier());
7401 Parser.Lex(); // Eat the identifier.
7402 return false;
7403}
7404
Jason W Kimd7c9e082011-12-20 17:38:12 +00007405/// parseDirectiveArch
7406/// ::= .arch token
7407bool ARMAsmParser::parseDirectiveArch(SMLoc L) {
7408 return true;
7409}
7410
7411/// parseDirectiveEabiAttr
7412/// ::= .eabi_attribute int, int
7413bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
7414 return true;
7415}
7416
Sean Callanan90b70972010-04-07 20:29:34 +00007417extern "C" void LLVMInitializeARMAsmLexer();
7418
Kevin Enderby9c41fa82009-10-30 22:55:57 +00007419/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007420extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00007421 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
7422 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00007423 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007424}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00007425
Chris Lattner0692ee62010-09-06 19:11:01 +00007426#define GET_REGISTER_MATCHER
7427#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00007428#include "ARMGenAsmMatcher.inc"