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