blob: 10e3885406b48558aacdd0e74ed6e5d1b5d6da14 [file] [log] [blame]
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00001//===-- ARMAsmParser.cpp - Parse ARM assembly to MCInst instructions ------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Evan Cheng94b95502011-07-26 00:24:13 +000010#include "MCTargetDesc/ARMBaseInfo.h"
Evan Chengee04a6d2011-07-20 23:34:39 +000011#include "MCTargetDesc/ARMAddressingModes.h"
12#include "MCTargetDesc/ARMMCExpr.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000013#include "llvm/MC/MCParser/MCAsmLexer.h"
14#include "llvm/MC/MCParser/MCAsmParser.h"
15#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Rafael Espindola64695402011-05-16 16:17:21 +000016#include "llvm/MC/MCAsmInfo.h"
Jim Grosbach642fc9c2010-11-05 22:33:53 +000017#include "llvm/MC/MCContext.h"
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000018#include "llvm/MC/MCStreamer.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Evan Cheng78011362011-08-23 20:15:21 +000021#include "llvm/MC/MCInstrDesc.h"
Evan Cheng94b95502011-07-26 00:24:13 +000022#include "llvm/MC/MCRegisterInfo.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000023#include "llvm/MC/MCSubtargetInfo.h"
Evan Cheng94b95502011-07-26 00:24:13 +000024#include "llvm/MC/MCTargetAsmParser.h"
Jim Grosbach89df9962011-08-26 21:43:41 +000025#include "llvm/Support/MathExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000026#include "llvm/Support/SourceMgr.h"
Evan Cheng3e74d6f2011-08-24 18:08:43 +000027#include "llvm/Support/TargetRegistry.h"
Daniel Dunbarfa315de2010-08-11 06:37:12 +000028#include "llvm/Support/raw_ostream.h"
Jim Grosbach11e03e72011-08-22 18:50:36 +000029#include "llvm/ADT/BitVector.h"
Benjamin Kramer75ca4b92011-07-08 21:06:23 +000030#include "llvm/ADT/OwningPtr.h"
Evan Cheng94b95502011-07-26 00:24:13 +000031#include "llvm/ADT/STLExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000032#include "llvm/ADT/SmallVector.h"
Daniel Dunbar345a9a62010-08-11 06:37:20 +000033#include "llvm/ADT/StringSwitch.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000034#include "llvm/ADT/Twine.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000035
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000036using namespace llvm;
37
Chris Lattner3a697562010-10-28 17:20:03 +000038namespace {
Bill Wendling146018f2010-11-06 21:42:12 +000039
40class ARMOperand;
Jim Grosbach16c74252010-10-29 14:46:02 +000041
Jim Grosbach7636bf62011-12-02 00:35:16 +000042enum VectorLaneTy { NoLanes, AllLanes, IndexedLane };
Jim Grosbach98b05a52011-11-30 01:09:44 +000043
Evan Cheng94b95502011-07-26 00:24:13 +000044class ARMAsmParser : public MCTargetAsmParser {
Evan Chengffc0e732011-07-09 05:47:46 +000045 MCSubtargetInfo &STI;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000046 MCAsmParser &Parser;
Jim Grosbach28f08c92012-03-05 19:33:30 +000047 const MCRegisterInfo *MRI;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000048
Jim Grosbacha39cda72011-12-14 02:16:11 +000049 // Map of register aliases registers via the .req directive.
50 StringMap<unsigned> RegisterReqs;
51
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000052 struct {
53 ARMCC::CondCodes Cond; // Condition for IT block.
54 unsigned Mask:4; // Condition mask for instructions.
55 // Starting at first 1 (from lsb).
56 // '1' condition as indicated in IT.
57 // '0' inverse of condition (else).
58 // Count of instructions in IT block is
59 // 4 - trailingzeroes(mask)
60
61 bool FirstCond; // Explicit flag for when we're parsing the
62 // First instruction in the IT block. It's
63 // implied in the mask, so needs special
64 // handling.
65
66 unsigned CurPosition; // Current position in parsing of IT
67 // block. In range [0,3]. Initialized
68 // according to count of instructions in block.
69 // ~0U if no active IT block.
70 } ITState;
71 bool inITBlock() { return ITState.CurPosition != ~0U;}
Jim Grosbacha1109882011-09-02 23:22:08 +000072 void forwardITPosition() {
73 if (!inITBlock()) return;
74 // Move to the next instruction in the IT block, if there is one. If not,
75 // mark the block as done.
76 unsigned TZ = CountTrailingZeros_32(ITState.Mask);
77 if (++ITState.CurPosition == 5 - TZ)
78 ITState.CurPosition = ~0U; // Done with the IT block after this.
79 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000080
81
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000082 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000083 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
84
85 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000086 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
87
Jim Grosbach1355cf12011-07-26 17:10:22 +000088 int tryParseRegister();
89 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d87ec22011-07-26 20:41:24 +000090 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000091 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +000092 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000093 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
94 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbach7ce05792011-08-03 23:50:40 +000095 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
96 unsigned &ShiftAmount);
Jim Grosbach1355cf12011-07-26 17:10:22 +000097 bool parseDirectiveWord(unsigned Size, SMLoc L);
98 bool parseDirectiveThumb(SMLoc L);
Jim Grosbach9a70df92011-12-07 18:04:19 +000099 bool parseDirectiveARM(SMLoc L);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000100 bool parseDirectiveThumbFunc(SMLoc L);
101 bool parseDirectiveCode(SMLoc L);
102 bool parseDirectiveSyntax(SMLoc L);
Jim Grosbacha39cda72011-12-14 02:16:11 +0000103 bool parseDirectiveReq(StringRef Name, SMLoc L);
104 bool parseDirectiveUnreq(SMLoc L);
Jason W Kimd7c9e082011-12-20 17:38:12 +0000105 bool parseDirectiveArch(SMLoc L);
106 bool parseDirectiveEabiAttr(SMLoc L);
Kevin Enderby515d5092009-10-15 20:48:48 +0000107
Jim Grosbach1355cf12011-07-26 17:10:22 +0000108 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach89df9962011-08-26 21:43:41 +0000109 bool &CarrySetting, unsigned &ProcessorIMod,
110 StringRef &ITMask);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000111 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +0000112 bool &CanAcceptPredicationCode);
Jim Grosbach16c74252010-10-29 14:46:02 +0000113
Evan Chengebdeeab2011-07-08 01:53:10 +0000114 bool isThumb() const {
115 // FIXME: Can tablegen auto-generate this?
Evan Chengffc0e732011-07-09 05:47:46 +0000116 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000117 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000118 bool isThumbOne() const {
Evan Chengffc0e732011-07-09 05:47:46 +0000119 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000120 }
Jim Grosbach47a0d522011-08-16 20:45:50 +0000121 bool isThumbTwo() const {
122 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
123 }
Jim Grosbach194bd892011-08-16 22:20:01 +0000124 bool hasV6Ops() const {
125 return STI.getFeatureBits() & ARM::HasV6Ops;
126 }
James Molloyacad68d2011-09-28 14:21:38 +0000127 bool hasV7Ops() const {
128 return STI.getFeatureBits() & ARM::HasV7Ops;
129 }
Evan Cheng32869202011-07-08 22:36:29 +0000130 void SwitchMode() {
Evan Chengffc0e732011-07-09 05:47:46 +0000131 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
132 setAvailableFeatures(FB);
Evan Cheng32869202011-07-08 22:36:29 +0000133 }
James Molloyacad68d2011-09-28 14:21:38 +0000134 bool isMClass() const {
135 return STI.getFeatureBits() & ARM::FeatureMClass;
136 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000137
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000138 /// @name Auto-generated Match Functions
139 /// {
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000140
Chris Lattner0692ee62010-09-06 19:11:01 +0000141#define GET_ASSEMBLER_HEADER
142#include "ARMGenAsmMatcher.inc"
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000143
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000144 /// }
145
Jim Grosbach89df9962011-08-26 21:43:41 +0000146 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000147 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000148 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000149 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000150 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000151 OperandMatchResultTy parseCoprocOptionOperand(
152 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000153 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000154 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000155 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000156 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000157 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000158 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachf6c05252011-07-21 17:23:04 +0000159 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
160 StringRef Op, int Low, int High);
161 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
162 return parsePKHImm(O, "lsl", 0, 31);
163 }
164 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
165 return parsePKHImm(O, "asr", 1, 32);
166 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000167 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach580f4a92011-07-25 22:20:28 +0000168 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000169 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000170 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000171 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach251bf252011-08-10 21:56:18 +0000172 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9d390362011-10-03 23:38:36 +0000173 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach862019c2011-10-18 23:02:30 +0000174 OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7636bf62011-12-02 00:35:16 +0000175 OperandMatchResultTy parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000176
177 // Asm Match Converter Methods
Jim Grosbacha77295d2011-09-08 22:07:06 +0000178 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
179 const SmallVectorImpl<MCParsedAsmOperand*> &);
180 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
181 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheeec0252011-09-08 00:39:19 +0000182 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
183 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachee2c2a42011-09-16 21:55:56 +0000184 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
185 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000186 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000187 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson9ab0f252011-08-26 20:43:14 +0000188 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
189 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach548340c2011-08-11 19:22:40 +0000190 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
191 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000192 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000193 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7b8f46c2011-08-11 21:17:22 +0000194 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
195 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000196 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
197 const SmallVectorImpl<MCParsedAsmOperand*> &);
198 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
199 const SmallVectorImpl<MCParsedAsmOperand*> &);
200 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
201 const SmallVectorImpl<MCParsedAsmOperand*> &);
202 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
203 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000204 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
205 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach14605d12011-08-11 20:28:23 +0000206 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
207 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach623a4542011-08-10 22:42:16 +0000208 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
209 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach88ae2bc2011-08-19 22:07:46 +0000210 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
211 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach12431322011-10-24 22:16:58 +0000212 bool cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
213 const SmallVectorImpl<MCParsedAsmOperand*> &);
214 bool cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
215 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach4334e032011-10-31 21:50:31 +0000216 bool cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
217 const SmallVectorImpl<MCParsedAsmOperand*> &);
218 bool cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
219 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach189610f2011-07-26 18:25:39 +0000220
221 bool validateInstruction(MCInst &Inst,
222 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach83ec8772011-11-10 23:42:14 +0000223 bool processInstruction(MCInst &Inst,
Jim Grosbachf8fce712011-08-11 17:35:48 +0000224 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachd54b4e62011-08-16 21:12:37 +0000225 bool shouldOmitCCOutOperand(StringRef Mnemonic,
226 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach189610f2011-07-26 18:25:39 +0000227
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000228public:
Jim Grosbach47a0d522011-08-16 20:45:50 +0000229 enum ARMMatchResultTy {
Jim Grosbach194bd892011-08-16 22:20:01 +0000230 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000231 Match_RequiresNotITBlock,
Jim Grosbach194bd892011-08-16 22:20:01 +0000232 Match_RequiresV6,
233 Match_RequiresThumb2
Jim Grosbach47a0d522011-08-16 20:45:50 +0000234 };
235
Evan Chengffc0e732011-07-09 05:47:46 +0000236 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng94b95502011-07-26 00:24:13 +0000237 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Chengebdeeab2011-07-08 01:53:10 +0000238 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng32869202011-07-08 22:36:29 +0000239
Jim Grosbach28f08c92012-03-05 19:33:30 +0000240 // Cache the MCRegisterInfo.
241 MRI = &getContext().getRegisterInfo();
242
Evan Chengebdeeab2011-07-08 01:53:10 +0000243 // Initialize the set of available features.
Evan Chengffc0e732011-07-09 05:47:46 +0000244 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000245
246 // Not in an ITBlock to start with.
247 ITState.CurPosition = ~0U;
Evan Chengebdeeab2011-07-08 01:53:10 +0000248 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000249
Jim Grosbach1355cf12011-07-26 17:10:22 +0000250 // Implementation of the MCTargetAsmParser interface:
251 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
252 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbach189610f2011-07-26 18:25:39 +0000253 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000254 bool ParseDirective(AsmToken DirectiveID);
255
Jim Grosbach47a0d522011-08-16 20:45:50 +0000256 unsigned checkTargetMatchPredicate(MCInst &Inst);
257
Jim Grosbach1355cf12011-07-26 17:10:22 +0000258 bool MatchAndEmitInstruction(SMLoc IDLoc,
259 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
260 MCStreamer &Out);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000261};
Jim Grosbach16c74252010-10-29 14:46:02 +0000262} // end anonymous namespace
263
Chris Lattner3a697562010-10-28 17:20:03 +0000264namespace {
265
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000266/// ARMOperand - Instances of this class represent a parsed ARM machine
267/// instruction.
Bill Wendling146018f2010-11-06 21:42:12 +0000268class ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000269 enum KindTy {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000270 k_CondCode,
271 k_CCOut,
272 k_ITCondMask,
273 k_CoprocNum,
274 k_CoprocReg,
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000275 k_CoprocOption,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000276 k_Immediate,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000277 k_MemBarrierOpt,
278 k_Memory,
279 k_PostIndexRegister,
280 k_MSRMask,
281 k_ProcIFlags,
Jim Grosbach460a9052011-10-07 23:56:00 +0000282 k_VectorIndex,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000283 k_Register,
284 k_RegisterList,
285 k_DPRRegisterList,
286 k_SPRRegisterList,
Jim Grosbach862019c2011-10-18 23:02:30 +0000287 k_VectorList,
Jim Grosbach98b05a52011-11-30 01:09:44 +0000288 k_VectorListAllLanes,
Jim Grosbach7636bf62011-12-02 00:35:16 +0000289 k_VectorListIndexed,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000290 k_ShiftedRegister,
291 k_ShiftedImmediate,
292 k_ShifterImmediate,
293 k_RotateImmediate,
294 k_BitfieldDescriptor,
295 k_Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000296 } Kind;
297
Sean Callanan76264762010-04-02 22:27:05 +0000298 SMLoc StartLoc, EndLoc;
Bill Wendling24d22d22010-11-18 21:50:54 +0000299 SmallVector<unsigned, 8> Registers;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000300
301 union {
302 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000303 ARMCC::CondCodes Val;
304 } CC;
305
306 struct {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000307 unsigned Val;
308 } Cop;
309
310 struct {
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000311 unsigned Val;
312 } CoprocOption;
313
314 struct {
Jim Grosbach89df9962011-08-26 21:43:41 +0000315 unsigned Mask:4;
316 } ITMask;
317
318 struct {
319 ARM_MB::MemBOpt Val;
320 } MBOpt;
321
322 struct {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000323 ARM_PROC::IFlags Val;
324 } IFlags;
325
326 struct {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000327 unsigned Val;
328 } MMask;
329
330 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000331 const char *Data;
332 unsigned Length;
333 } Tok;
334
335 struct {
336 unsigned RegNum;
337 } Reg;
338
Jim Grosbach862019c2011-10-18 23:02:30 +0000339 // A vector register list is a sequential list of 1 to 4 registers.
340 struct {
341 unsigned RegNum;
342 unsigned Count;
Jim Grosbach7636bf62011-12-02 00:35:16 +0000343 unsigned LaneIndex;
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +0000344 bool isDoubleSpaced;
Jim Grosbach862019c2011-10-18 23:02:30 +0000345 } VectorList;
346
Bill Wendling8155e5b2010-11-06 22:19:43 +0000347 struct {
Jim Grosbach460a9052011-10-07 23:56:00 +0000348 unsigned Val;
349 } VectorIndex;
350
351 struct {
Kevin Enderbycfe07242009-10-13 22:19:02 +0000352 const MCExpr *Val;
353 } Imm;
Jim Grosbach16c74252010-10-29 14:46:02 +0000354
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +0000355 /// Combined record for all forms of ARM address expressions.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000356 struct {
357 unsigned BaseRegNum;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000358 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
359 // was specified.
360 const MCConstantExpr *OffsetImm; // Offset immediate value
361 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
362 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbach57dcb852011-10-11 17:29:55 +0000363 unsigned ShiftImm; // shift for OffsetReg.
364 unsigned Alignment; // 0 = no alignment specified
Jim Grosbacheeaf1c12011-12-19 18:31:43 +0000365 // n = alignment in bytes (2, 4, 8, 16, or 32)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000366 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbache53c87b2011-10-11 15:59:20 +0000367 } Memory;
Owen Anderson00828302011-03-18 22:50:18 +0000368
369 struct {
Jim Grosbach7ce05792011-08-03 23:50:40 +0000370 unsigned RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000371 bool isAdd;
372 ARM_AM::ShiftOpc ShiftTy;
373 unsigned ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000374 } PostIdxReg;
375
376 struct {
Jim Grosbach580f4a92011-07-25 22:20:28 +0000377 bool isASR;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000378 unsigned Imm;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000379 } ShifterImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000380 struct {
381 ARM_AM::ShiftOpc ShiftTy;
382 unsigned SrcReg;
383 unsigned ShiftReg;
384 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000385 } RegShiftedReg;
Owen Anderson92a20222011-07-21 18:54:16 +0000386 struct {
387 ARM_AM::ShiftOpc ShiftTy;
388 unsigned SrcReg;
389 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000390 } RegShiftedImm;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000391 struct {
392 unsigned Imm;
393 } RotImm;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000394 struct {
395 unsigned LSB;
396 unsigned Width;
397 } Bitfield;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000398 };
Jim Grosbach16c74252010-10-29 14:46:02 +0000399
Bill Wendling146018f2010-11-06 21:42:12 +0000400 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
401public:
Sean Callanan76264762010-04-02 22:27:05 +0000402 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
403 Kind = o.Kind;
404 StartLoc = o.StartLoc;
405 EndLoc = o.EndLoc;
406 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000407 case k_CondCode:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000408 CC = o.CC;
409 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000410 case k_ITCondMask:
Jim Grosbach89df9962011-08-26 21:43:41 +0000411 ITMask = o.ITMask;
412 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000413 case k_Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000414 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000415 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000416 case k_CCOut:
417 case k_Register:
Sean Callanan76264762010-04-02 22:27:05 +0000418 Reg = o.Reg;
419 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000420 case k_RegisterList:
421 case k_DPRRegisterList:
422 case k_SPRRegisterList:
Bill Wendling24d22d22010-11-18 21:50:54 +0000423 Registers = o.Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000424 break;
Jim Grosbach862019c2011-10-18 23:02:30 +0000425 case k_VectorList:
Jim Grosbach98b05a52011-11-30 01:09:44 +0000426 case k_VectorListAllLanes:
Jim Grosbach7636bf62011-12-02 00:35:16 +0000427 case k_VectorListIndexed:
Jim Grosbach862019c2011-10-18 23:02:30 +0000428 VectorList = o.VectorList;
429 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000430 case k_CoprocNum:
431 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000432 Cop = o.Cop;
433 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000434 case k_CoprocOption:
435 CoprocOption = o.CoprocOption;
436 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000437 case k_Immediate:
Sean Callanan76264762010-04-02 22:27:05 +0000438 Imm = o.Imm;
439 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000440 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000441 MBOpt = o.MBOpt;
442 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000443 case k_Memory:
Jim Grosbache53c87b2011-10-11 15:59:20 +0000444 Memory = o.Memory;
Sean Callanan76264762010-04-02 22:27:05 +0000445 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000446 case k_PostIndexRegister:
Jim Grosbach7ce05792011-08-03 23:50:40 +0000447 PostIdxReg = o.PostIdxReg;
448 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000449 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000450 MMask = o.MMask;
451 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000452 case k_ProcIFlags:
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000453 IFlags = o.IFlags;
Owen Anderson00828302011-03-18 22:50:18 +0000454 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000455 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +0000456 ShifterImm = o.ShifterImm;
Owen Anderson00828302011-03-18 22:50:18 +0000457 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000458 case k_ShiftedRegister:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000459 RegShiftedReg = o.RegShiftedReg;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000460 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000461 case k_ShiftedImmediate:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000462 RegShiftedImm = o.RegShiftedImm;
Owen Anderson92a20222011-07-21 18:54:16 +0000463 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000464 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000465 RotImm = o.RotImm;
466 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000467 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000468 Bitfield = o.Bitfield;
469 break;
Jim Grosbach460a9052011-10-07 23:56:00 +0000470 case k_VectorIndex:
471 VectorIndex = o.VectorIndex;
472 break;
Sean Callanan76264762010-04-02 22:27:05 +0000473 }
474 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000475
Sean Callanan76264762010-04-02 22:27:05 +0000476 /// getStartLoc - Get the location of the first token of this operand.
477 SMLoc getStartLoc() const { return StartLoc; }
478 /// getEndLoc - Get the location of the last token of this operand.
479 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000480
Daniel Dunbar8462b302010-08-11 06:36:53 +0000481 ARMCC::CondCodes getCondCode() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000482 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000483 return CC.Val;
484 }
485
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000486 unsigned getCoproc() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000487 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000488 return Cop.Val;
489 }
490
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000491 StringRef getToken() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000492 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000493 return StringRef(Tok.Data, Tok.Length);
494 }
495
496 unsigned getReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000497 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling7729e062010-11-09 22:44:22 +0000498 return Reg.RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000499 }
500
Bill Wendling5fa22a12010-11-09 23:28:44 +0000501 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000502 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
503 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling24d22d22010-11-18 21:50:54 +0000504 return Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000505 }
506
Kevin Enderbycfe07242009-10-13 22:19:02 +0000507 const MCExpr *getImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000508 assert(isImm() && "Invalid access!");
Kevin Enderbycfe07242009-10-13 22:19:02 +0000509 return Imm.Val;
510 }
511
Jim Grosbach460a9052011-10-07 23:56:00 +0000512 unsigned getVectorIndex() const {
513 assert(Kind == k_VectorIndex && "Invalid access!");
514 return VectorIndex.Val;
515 }
516
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000517 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000518 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000519 return MBOpt.Val;
520 }
521
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000522 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000523 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000524 return IFlags.Val;
525 }
526
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000527 unsigned getMSRMask() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000528 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000529 return MMask.Val;
530 }
531
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000532 bool isCoprocNum() const { return Kind == k_CoprocNum; }
533 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000534 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000535 bool isCondCode() const { return Kind == k_CondCode; }
536 bool isCCOut() const { return Kind == k_CCOut; }
537 bool isITMask() const { return Kind == k_ITCondMask; }
538 bool isITCondCode() const { return Kind == k_CondCode; }
539 bool isImm() const { return Kind == k_Immediate; }
Jim Grosbach51222d12012-01-20 18:09:51 +0000540 bool isFPImm() const {
541 if (!isImm()) return false;
542 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
543 if (!CE) return false;
544 int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
545 return Val != -1;
546 }
Jim Grosbach4050bc42011-12-22 22:19:05 +0000547 bool isFBits16() const {
548 if (!isImm()) return false;
549 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
550 if (!CE) return false;
551 int64_t Value = CE->getValue();
552 return Value >= 0 && Value <= 16;
553 }
554 bool isFBits32() const {
555 if (!isImm()) return false;
556 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
557 if (!CE) return false;
558 int64_t Value = CE->getValue();
559 return Value >= 1 && Value <= 32;
560 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000561 bool isImm8s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000562 if (!isImm()) return false;
Jim Grosbacha77295d2011-09-08 22:07:06 +0000563 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
564 if (!CE) return false;
565 int64_t Value = CE->getValue();
566 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
567 }
Jim Grosbach72f39f82011-08-24 21:22:15 +0000568 bool isImm0_1020s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000569 if (!isImm()) return false;
Jim Grosbach72f39f82011-08-24 21:22:15 +0000570 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
571 if (!CE) return false;
572 int64_t Value = CE->getValue();
573 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
574 }
575 bool isImm0_508s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000576 if (!isImm()) return false;
Jim Grosbach72f39f82011-08-24 21:22:15 +0000577 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
578 if (!CE) return false;
579 int64_t Value = CE->getValue();
580 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
581 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000582 bool isImm0_255() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000583 if (!isImm()) return false;
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000584 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
585 if (!CE) return false;
586 int64_t Value = CE->getValue();
587 return Value >= 0 && Value < 256;
588 }
Jim Grosbach587f5062011-12-02 23:34:39 +0000589 bool isImm0_1() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000590 if (!isImm()) return false;
Jim Grosbach587f5062011-12-02 23:34:39 +0000591 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
592 if (!CE) return false;
593 int64_t Value = CE->getValue();
594 return Value >= 0 && Value < 2;
595 }
596 bool isImm0_3() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000597 if (!isImm()) return false;
Jim Grosbach587f5062011-12-02 23:34:39 +0000598 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
599 if (!CE) return false;
600 int64_t Value = CE->getValue();
601 return Value >= 0 && Value < 4;
602 }
Jim Grosbach83ab0702011-07-13 22:01:08 +0000603 bool isImm0_7() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000604 if (!isImm()) return false;
Jim Grosbach83ab0702011-07-13 22:01:08 +0000605 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
606 if (!CE) return false;
607 int64_t Value = CE->getValue();
608 return Value >= 0 && Value < 8;
609 }
610 bool isImm0_15() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000611 if (!isImm()) return false;
Jim Grosbach83ab0702011-07-13 22:01:08 +0000612 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
613 if (!CE) return false;
614 int64_t Value = CE->getValue();
615 return Value >= 0 && Value < 16;
616 }
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000617 bool isImm0_31() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000618 if (!isImm()) return false;
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000619 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
620 if (!CE) return false;
621 int64_t Value = CE->getValue();
622 return Value >= 0 && Value < 32;
623 }
Jim Grosbach730fe6c2011-12-08 01:30:04 +0000624 bool isImm0_63() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000625 if (!isImm()) return false;
Jim Grosbach730fe6c2011-12-08 01:30:04 +0000626 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
627 if (!CE) return false;
628 int64_t Value = CE->getValue();
629 return Value >= 0 && Value < 64;
630 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000631 bool isImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000632 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000633 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
634 if (!CE) return false;
635 int64_t Value = CE->getValue();
636 return Value == 8;
637 }
638 bool isImm16() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000639 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000640 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
641 if (!CE) return false;
642 int64_t Value = CE->getValue();
643 return Value == 16;
644 }
645 bool isImm32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000646 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000647 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
648 if (!CE) return false;
649 int64_t Value = CE->getValue();
650 return Value == 32;
651 }
Jim Grosbach6b044c22011-12-08 22:06:06 +0000652 bool isShrImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000653 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000654 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
655 if (!CE) return false;
656 int64_t Value = CE->getValue();
657 return Value > 0 && Value <= 8;
658 }
659 bool isShrImm16() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000660 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000661 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
662 if (!CE) return false;
663 int64_t Value = CE->getValue();
664 return Value > 0 && Value <= 16;
665 }
666 bool isShrImm32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000667 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000668 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
669 if (!CE) return false;
670 int64_t Value = CE->getValue();
671 return Value > 0 && Value <= 32;
672 }
673 bool isShrImm64() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000674 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000675 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
676 if (!CE) return false;
677 int64_t Value = CE->getValue();
678 return Value > 0 && Value <= 64;
679 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000680 bool isImm1_7() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000681 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000682 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
683 if (!CE) return false;
684 int64_t Value = CE->getValue();
685 return Value > 0 && Value < 8;
686 }
687 bool isImm1_15() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000688 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000689 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
690 if (!CE) return false;
691 int64_t Value = CE->getValue();
692 return Value > 0 && Value < 16;
693 }
694 bool isImm1_31() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000695 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000696 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
697 if (!CE) return false;
698 int64_t Value = CE->getValue();
699 return Value > 0 && Value < 32;
700 }
Jim Grosbachf4943352011-07-25 23:09:14 +0000701 bool isImm1_16() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000702 if (!isImm()) return false;
Jim Grosbachf4943352011-07-25 23:09:14 +0000703 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
704 if (!CE) return false;
705 int64_t Value = CE->getValue();
706 return Value > 0 && Value < 17;
707 }
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000708 bool isImm1_32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000709 if (!isImm()) return false;
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000710 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
711 if (!CE) return false;
712 int64_t Value = CE->getValue();
713 return Value > 0 && Value < 33;
714 }
Jim Grosbachee10ff82011-11-10 19:18:01 +0000715 bool isImm0_32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000716 if (!isImm()) return false;
Jim Grosbachee10ff82011-11-10 19:18:01 +0000717 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
718 if (!CE) return false;
719 int64_t Value = CE->getValue();
720 return Value >= 0 && Value < 33;
721 }
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000722 bool isImm0_65535() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000723 if (!isImm()) return false;
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000724 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
725 if (!CE) return false;
726 int64_t Value = CE->getValue();
727 return Value >= 0 && Value < 65536;
728 }
Jim Grosbachffa32252011-07-19 19:13:28 +0000729 bool isImm0_65535Expr() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000730 if (!isImm()) return false;
Jim Grosbachffa32252011-07-19 19:13:28 +0000731 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
732 // If it's not a constant expression, it'll generate a fixup and be
733 // handled later.
734 if (!CE) return true;
735 int64_t Value = CE->getValue();
736 return Value >= 0 && Value < 65536;
737 }
Jim Grosbached838482011-07-26 16:24:27 +0000738 bool isImm24bit() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000739 if (!isImm()) return false;
Jim Grosbached838482011-07-26 16:24:27 +0000740 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
741 if (!CE) return false;
742 int64_t Value = CE->getValue();
743 return Value >= 0 && Value <= 0xffffff;
744 }
Jim Grosbach70939ee2011-08-17 21:51:27 +0000745 bool isImmThumbSR() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000746 if (!isImm()) return false;
Jim Grosbach70939ee2011-08-17 21:51:27 +0000747 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
748 if (!CE) return false;
749 int64_t Value = CE->getValue();
750 return Value > 0 && Value < 33;
751 }
Jim Grosbachf6c05252011-07-21 17:23:04 +0000752 bool isPKHLSLImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000753 if (!isImm()) return false;
Jim Grosbachf6c05252011-07-21 17:23:04 +0000754 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
755 if (!CE) return false;
756 int64_t Value = CE->getValue();
757 return Value >= 0 && Value < 32;
758 }
759 bool isPKHASRImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000760 if (!isImm()) return false;
Jim Grosbachf6c05252011-07-21 17:23:04 +0000761 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
762 if (!CE) return false;
763 int64_t Value = CE->getValue();
764 return Value > 0 && Value <= 32;
765 }
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000766 bool isARMSOImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000767 if (!isImm()) return false;
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000768 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
769 if (!CE) return false;
770 int64_t Value = CE->getValue();
771 return ARM_AM::getSOImmVal(Value) != -1;
772 }
Jim Grosbache70ec842011-10-28 22:50:54 +0000773 bool isARMSOImmNot() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000774 if (!isImm()) return false;
Jim Grosbache70ec842011-10-28 22:50:54 +0000775 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
776 if (!CE) return false;
777 int64_t Value = CE->getValue();
778 return ARM_AM::getSOImmVal(~Value) != -1;
779 }
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000780 bool isARMSOImmNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000781 if (!isImm()) return false;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000782 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
783 if (!CE) return false;
784 int64_t Value = CE->getValue();
Jim Grosbachb22e70d2012-03-29 21:19:52 +0000785 // Negation must be representable as an so_imm and be non-zero.
786 return Value && ARM_AM::getSOImmVal(-Value) != -1;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000787 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000788 bool isT2SOImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000789 if (!isImm()) return false;
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000790 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
791 if (!CE) return false;
792 int64_t Value = CE->getValue();
793 return ARM_AM::getT2SOImmVal(Value) != -1;
794 }
Jim Grosbach89a63372011-10-28 22:36:30 +0000795 bool isT2SOImmNot() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000796 if (!isImm()) return false;
Jim Grosbach89a63372011-10-28 22:36:30 +0000797 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
798 if (!CE) return false;
799 int64_t Value = CE->getValue();
800 return ARM_AM::getT2SOImmVal(~Value) != -1;
801 }
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000802 bool isT2SOImmNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000803 if (!isImm()) return false;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000804 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
805 if (!CE) return false;
806 int64_t Value = CE->getValue();
Jim Grosbachb22e70d2012-03-29 21:19:52 +0000807 // Negation must be representable as a t2_so_imm and be non-zero.
808 return Value && ARM_AM::getT2SOImmVal(-Value) != -1;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000809 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000810 bool isSetEndImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000811 if (!isImm()) return false;
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000812 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
813 if (!CE) return false;
814 int64_t Value = CE->getValue();
815 return Value == 1 || Value == 0;
816 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000817 bool isReg() const { return Kind == k_Register; }
818 bool isRegList() const { return Kind == k_RegisterList; }
819 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
820 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
821 bool isToken() const { return Kind == k_Token; }
822 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
823 bool isMemory() const { return Kind == k_Memory; }
824 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
825 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
826 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
827 bool isRotImm() const { return Kind == k_RotateImmediate; }
828 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
829 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000830 bool isPostIdxReg() const {
Jim Grosbach430052b2011-11-14 17:52:47 +0000831 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000832 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000833 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000834 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000835 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000836 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000837 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
838 (alignOK || Memory.Alignment == 0);
839 }
Jim Grosbach0b4c6732012-01-18 22:46:46 +0000840 bool isMemPCRelImm12() const {
841 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
842 return false;
843 // Base register must be PC.
844 if (Memory.BaseRegNum != ARM::PC)
845 return false;
846 // Immediate offset in range [-4095, 4095].
847 if (!Memory.OffsetImm) return true;
848 int64_t Val = Memory.OffsetImm->getValue();
849 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
850 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000851 bool isAlignedMemory() const {
852 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000853 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000854 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000855 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000856 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000857 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000858 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000859 if (!Memory.OffsetImm) return true;
860 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000861 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000862 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000863 bool isAM2OffsetImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000864 if (!isImm()) return false;
Jim Grosbach039c2e12011-08-04 23:01:30 +0000865 // Immediate offset in range [-4095, 4095].
866 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
867 if (!CE) return false;
868 int64_t Val = CE->getValue();
869 return Val > -4096 && Val < 4096;
870 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000871 bool isAddrMode3() const {
Jim Grosbach2f196742011-12-19 23:06:24 +0000872 // If we have an immediate that's not a constant, treat it as a label
873 // reference needing a fixup. If it is a constant, it's something else
874 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000875 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach2f196742011-12-19 23:06:24 +0000876 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000877 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000878 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000879 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000880 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000881 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000882 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000883 if (!Memory.OffsetImm) return true;
884 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000885 return Val > -256 && Val < 256;
886 }
887 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000888 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000889 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000890 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000891 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
892 // Immediate offset in range [-255, 255].
893 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
894 if (!CE) return false;
895 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000896 // Special case, #-0 is INT32_MIN.
897 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000898 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000899 bool isAddrMode5() const {
Jim Grosbach681460f2011-11-01 01:24:45 +0000900 // If we have an immediate that's not a constant, treat it as a label
901 // reference needing a fixup. If it is a constant, it's something else
902 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000903 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach681460f2011-11-01 01:24:45 +0000904 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000905 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000906 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000907 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000908 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000909 if (!Memory.OffsetImm) return true;
910 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000911 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbach681460f2011-11-01 01:24:45 +0000912 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000913 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000914 bool isMemTBB() 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::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000917 return false;
918 return true;
919 }
920 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000921 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000922 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
923 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000924 return false;
925 return true;
926 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000927 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000928 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000929 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000930 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000931 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000932 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000933 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
934 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000935 return false;
936 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000937 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000938 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000939 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000940 return false;
941 return true;
942 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000943 bool isMemThumbRR() const {
944 // Thumb reg+reg addressing is simple. Just two registers, a base and
945 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000946 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000947 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000948 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000949 return isARMLowRegister(Memory.BaseRegNum) &&
950 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000951 }
952 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000953 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000954 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000955 return false;
956 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000957 if (!Memory.OffsetImm) return true;
958 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000959 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
960 }
Jim Grosbach38466302011-08-19 18:55:51 +0000961 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000962 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000963 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000964 return false;
965 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000966 if (!Memory.OffsetImm) return true;
967 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +0000968 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
969 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000970 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000971 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000972 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000973 return false;
974 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000975 if (!Memory.OffsetImm) return true;
976 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000977 return Val >= 0 && Val <= 31;
978 }
Jim Grosbachecd85892011-08-19 18:13:48 +0000979 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000980 if (!isMemory() || Memory.OffsetRegNum != 0 ||
981 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +0000982 return false;
983 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000984 if (!Memory.OffsetImm) return true;
985 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000986 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000987 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000988 bool isMemImm8s4Offset() const {
Jim Grosbach2f196742011-12-19 23:06:24 +0000989 // If we have an immediate that's not a constant, treat it as a label
990 // reference needing a fixup. If it is a constant, it's something else
991 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000992 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach2f196742011-12-19 23:06:24 +0000993 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000994 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000995 return false;
996 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000997 if (!Memory.OffsetImm) return true;
998 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +0000999 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
1000 }
Jim Grosbachb6aed502011-09-09 18:37:27 +00001001 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001002 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +00001003 return false;
1004 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001005 if (!Memory.OffsetImm) return true;
1006 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +00001007 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
1008 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001009 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001010 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001011 return false;
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001012 // Base reg of PC isn't allowed for these encodings.
1013 if (Memory.BaseRegNum == ARM::PC) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001014 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001015 if (!Memory.OffsetImm) return true;
1016 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +00001017 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001018 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001019 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001020 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001021 return false;
1022 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001023 if (!Memory.OffsetImm) return true;
1024 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001025 return Val >= 0 && Val < 256;
1026 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001027 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001028 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001029 return false;
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001030 // Base reg of PC isn't allowed for these encodings.
1031 if (Memory.BaseRegNum == ARM::PC) return false;
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001032 // Immediate offset in range [-255, -1].
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001033 if (!Memory.OffsetImm) return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001034 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001035 return (Val == INT32_MIN) || (Val > -256 && Val < 0);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001036 }
1037 bool isMemUImm12Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001038 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001039 return false;
1040 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001041 if (!Memory.OffsetImm) return true;
1042 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001043 return (Val >= 0 && Val < 4096);
1044 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001045 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +00001046 // If we have an immediate that's not a constant, treat it as a label
1047 // reference needing a fixup. If it is a constant, it's something else
1048 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001049 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +00001050 return true;
1051
Jim Grosbach57dcb852011-10-11 17:29:55 +00001052 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001053 return false;
1054 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001055 if (!Memory.OffsetImm) return true;
1056 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +00001057 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001058 }
1059 bool isPostIdxImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001060 if (!isImm()) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001061 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1062 if (!CE) return false;
1063 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +00001064 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001065 }
Jim Grosbach2bd01182011-10-11 21:55:36 +00001066 bool isPostIdxImm8s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001067 if (!isImm()) return false;
Jim Grosbach2bd01182011-10-11 21:55:36 +00001068 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1069 if (!CE) return false;
1070 int64_t Val = CE->getValue();
1071 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1072 (Val == INT32_MIN);
1073 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001074
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001075 bool isMSRMask() const { return Kind == k_MSRMask; }
1076 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001077
Jim Grosbach0e387b22011-10-17 22:26:03 +00001078 // NEON operands.
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001079 bool isSingleSpacedVectorList() const {
1080 return Kind == k_VectorList && !VectorList.isDoubleSpaced;
1081 }
1082 bool isDoubleSpacedVectorList() const {
1083 return Kind == k_VectorList && VectorList.isDoubleSpaced;
1084 }
Jim Grosbach862019c2011-10-18 23:02:30 +00001085 bool isVecListOneD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001086 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach862019c2011-10-18 23:02:30 +00001087 return VectorList.Count == 1;
1088 }
1089
Jim Grosbach28f08c92012-03-05 19:33:30 +00001090 bool isVecListDPair() const {
1091 if (!isSingleSpacedVectorList()) return false;
1092 return (ARMMCRegisterClasses[ARM::DPairRegClassID]
1093 .contains(VectorList.RegNum));
1094 }
1095
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001096 bool isVecListThreeD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001097 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001098 return VectorList.Count == 3;
1099 }
1100
Jim Grosbachb6310312011-10-21 20:35:01 +00001101 bool isVecListFourD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001102 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachb6310312011-10-21 20:35:01 +00001103 return VectorList.Count == 4;
1104 }
1105
Jim Grosbachc3384c92012-03-05 21:43:40 +00001106 bool isVecListDPairSpaced() const {
Kevin Enderby9f2e1602012-03-20 17:41:51 +00001107 if (isSingleSpacedVectorList()) return false;
Jim Grosbachc3384c92012-03-05 21:43:40 +00001108 return (ARMMCRegisterClasses[ARM::DPairSpcRegClassID]
1109 .contains(VectorList.RegNum));
1110 }
1111
Jim Grosbachc387fc62012-01-23 23:20:46 +00001112 bool isVecListThreeQ() const {
1113 if (!isDoubleSpacedVectorList()) return false;
1114 return VectorList.Count == 3;
1115 }
1116
Jim Grosbach7945ead2012-01-24 00:43:12 +00001117 bool isVecListFourQ() const {
1118 if (!isDoubleSpacedVectorList()) return false;
1119 return VectorList.Count == 4;
1120 }
1121
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001122 bool isSingleSpacedVectorAllLanes() const {
1123 return Kind == k_VectorListAllLanes && !VectorList.isDoubleSpaced;
1124 }
1125 bool isDoubleSpacedVectorAllLanes() const {
1126 return Kind == k_VectorListAllLanes && VectorList.isDoubleSpaced;
1127 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00001128 bool isVecListOneDAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001129 if (!isSingleSpacedVectorAllLanes()) return false;
Jim Grosbach98b05a52011-11-30 01:09:44 +00001130 return VectorList.Count == 1;
1131 }
1132
Jim Grosbachc0fc4502012-03-06 22:01:44 +00001133 bool isVecListDPairAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001134 if (!isSingleSpacedVectorAllLanes()) return false;
Jim Grosbachc0fc4502012-03-06 22:01:44 +00001135 return (ARMMCRegisterClasses[ARM::DPairRegClassID]
1136 .contains(VectorList.RegNum));
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001137 }
1138
Jim Grosbach4d0983a2012-03-06 23:10:38 +00001139 bool isVecListDPairSpacedAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001140 if (!isDoubleSpacedVectorAllLanes()) return false;
Jim Grosbach13af2222011-11-30 18:21:25 +00001141 return VectorList.Count == 2;
1142 }
1143
Jim Grosbach5e59f7e2012-01-24 23:47:04 +00001144 bool isVecListThreeDAllLanes() const {
1145 if (!isSingleSpacedVectorAllLanes()) return false;
1146 return VectorList.Count == 3;
1147 }
1148
1149 bool isVecListThreeQAllLanes() const {
1150 if (!isDoubleSpacedVectorAllLanes()) return false;
1151 return VectorList.Count == 3;
1152 }
1153
Jim Grosbacha57a36a2012-01-25 00:01:08 +00001154 bool isVecListFourDAllLanes() const {
1155 if (!isSingleSpacedVectorAllLanes()) return false;
1156 return VectorList.Count == 4;
1157 }
1158
1159 bool isVecListFourQAllLanes() const {
1160 if (!isDoubleSpacedVectorAllLanes()) return false;
1161 return VectorList.Count == 4;
1162 }
1163
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001164 bool isSingleSpacedVectorIndexed() const {
1165 return Kind == k_VectorListIndexed && !VectorList.isDoubleSpaced;
1166 }
1167 bool isDoubleSpacedVectorIndexed() const {
1168 return Kind == k_VectorListIndexed && VectorList.isDoubleSpaced;
1169 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00001170 bool isVecListOneDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001171 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach7636bf62011-12-02 00:35:16 +00001172 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1173 }
1174
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001175 bool isVecListOneDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001176 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001177 return VectorList.Count == 1 && VectorList.LaneIndex <= 3;
1178 }
1179
1180 bool isVecListOneDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001181 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001182 return VectorList.Count == 1 && VectorList.LaneIndex <= 1;
1183 }
1184
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001185 bool isVecListTwoDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001186 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001187 return VectorList.Count == 2 && VectorList.LaneIndex <= 7;
1188 }
1189
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001190 bool isVecListTwoDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001191 if (!isSingleSpacedVectorIndexed()) return false;
1192 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1193 }
1194
1195 bool isVecListTwoQWordIndexed() const {
1196 if (!isDoubleSpacedVectorIndexed()) return false;
1197 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1198 }
1199
1200 bool isVecListTwoQHWordIndexed() const {
1201 if (!isDoubleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001202 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1203 }
1204
1205 bool isVecListTwoDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001206 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001207 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1208 }
1209
Jim Grosbach3a678af2012-01-23 21:53:26 +00001210 bool isVecListThreeDByteIndexed() const {
1211 if (!isSingleSpacedVectorIndexed()) return false;
1212 return VectorList.Count == 3 && VectorList.LaneIndex <= 7;
1213 }
1214
1215 bool isVecListThreeDHWordIndexed() const {
1216 if (!isSingleSpacedVectorIndexed()) return false;
1217 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1218 }
1219
1220 bool isVecListThreeQWordIndexed() const {
1221 if (!isDoubleSpacedVectorIndexed()) return false;
1222 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1223 }
1224
1225 bool isVecListThreeQHWordIndexed() const {
1226 if (!isDoubleSpacedVectorIndexed()) return false;
1227 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1228 }
1229
1230 bool isVecListThreeDWordIndexed() const {
1231 if (!isSingleSpacedVectorIndexed()) return false;
1232 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1233 }
1234
Jim Grosbache983a132012-01-24 18:37:25 +00001235 bool isVecListFourDByteIndexed() const {
1236 if (!isSingleSpacedVectorIndexed()) return false;
1237 return VectorList.Count == 4 && VectorList.LaneIndex <= 7;
1238 }
1239
1240 bool isVecListFourDHWordIndexed() const {
1241 if (!isSingleSpacedVectorIndexed()) return false;
1242 return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1243 }
1244
1245 bool isVecListFourQWordIndexed() const {
1246 if (!isDoubleSpacedVectorIndexed()) return false;
1247 return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1248 }
1249
1250 bool isVecListFourQHWordIndexed() const {
1251 if (!isDoubleSpacedVectorIndexed()) return false;
1252 return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1253 }
1254
1255 bool isVecListFourDWordIndexed() const {
1256 if (!isSingleSpacedVectorIndexed()) return false;
1257 return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1258 }
1259
Jim Grosbach460a9052011-10-07 23:56:00 +00001260 bool isVectorIndex8() const {
1261 if (Kind != k_VectorIndex) return false;
1262 return VectorIndex.Val < 8;
1263 }
1264 bool isVectorIndex16() const {
1265 if (Kind != k_VectorIndex) return false;
1266 return VectorIndex.Val < 4;
1267 }
1268 bool isVectorIndex32() const {
1269 if (Kind != k_VectorIndex) return false;
1270 return VectorIndex.Val < 2;
1271 }
1272
Jim Grosbach0e387b22011-10-17 22:26:03 +00001273 bool isNEONi8splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001274 if (!isImm()) return false;
Jim Grosbach0e387b22011-10-17 22:26:03 +00001275 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1276 // Must be a constant.
1277 if (!CE) return false;
1278 int64_t Value = CE->getValue();
1279 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1280 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +00001281 return Value >= 0 && Value < 256;
1282 }
Jim Grosbach460a9052011-10-07 23:56:00 +00001283
Jim Grosbachea461102011-10-17 23:09:09 +00001284 bool isNEONi16splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001285 if (!isImm()) return false;
Jim Grosbachea461102011-10-17 23:09:09 +00001286 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1287 // Must be a constant.
1288 if (!CE) return false;
1289 int64_t Value = CE->getValue();
1290 // i16 value in the range [0,255] or [0x0100, 0xff00]
1291 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1292 }
1293
Jim Grosbach6248a542011-10-18 00:22:00 +00001294 bool isNEONi32splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001295 if (!isImm()) return false;
Jim Grosbach6248a542011-10-18 00:22:00 +00001296 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1297 // Must be a constant.
1298 if (!CE) return false;
1299 int64_t Value = CE->getValue();
1300 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1301 return (Value >= 0 && Value < 256) ||
1302 (Value >= 0x0100 && Value <= 0xff00) ||
1303 (Value >= 0x010000 && Value <= 0xff0000) ||
1304 (Value >= 0x01000000 && Value <= 0xff000000);
1305 }
1306
1307 bool isNEONi32vmov() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001308 if (!isImm()) return false;
Jim Grosbach6248a542011-10-18 00:22:00 +00001309 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1310 // Must be a constant.
1311 if (!CE) return false;
1312 int64_t Value = CE->getValue();
1313 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1314 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1315 return (Value >= 0 && Value < 256) ||
1316 (Value >= 0x0100 && Value <= 0xff00) ||
1317 (Value >= 0x010000 && Value <= 0xff0000) ||
1318 (Value >= 0x01000000 && Value <= 0xff000000) ||
1319 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1320 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1321 }
Jim Grosbach9b087852011-12-19 23:51:07 +00001322 bool isNEONi32vmovNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001323 if (!isImm()) return false;
Jim Grosbach9b087852011-12-19 23:51:07 +00001324 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1325 // Must be a constant.
1326 if (!CE) return false;
1327 int64_t Value = ~CE->getValue();
1328 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1329 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1330 return (Value >= 0 && Value < 256) ||
1331 (Value >= 0x0100 && Value <= 0xff00) ||
1332 (Value >= 0x010000 && Value <= 0xff0000) ||
1333 (Value >= 0x01000000 && Value <= 0xff000000) ||
1334 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1335 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1336 }
Jim Grosbach6248a542011-10-18 00:22:00 +00001337
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001338 bool isNEONi64splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001339 if (!isImm()) return false;
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001340 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1341 // Must be a constant.
1342 if (!CE) return false;
1343 uint64_t Value = CE->getValue();
1344 // i64 value with each byte being either 0 or 0xff.
1345 for (unsigned i = 0; i < 8; ++i)
1346 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1347 return true;
1348 }
1349
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001350 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001351 // Add as immediates when possible. Null MCExpr = 0.
1352 if (Expr == 0)
1353 Inst.addOperand(MCOperand::CreateImm(0));
1354 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001355 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1356 else
1357 Inst.addOperand(MCOperand::CreateExpr(Expr));
1358 }
1359
Daniel Dunbar8462b302010-08-11 06:36:53 +00001360 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001361 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001362 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001363 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1364 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001365 }
1366
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001367 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1368 assert(N == 1 && "Invalid number of operands!");
1369 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1370 }
1371
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001372 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1373 assert(N == 1 && "Invalid number of operands!");
1374 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1375 }
1376
1377 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1378 assert(N == 1 && "Invalid number of operands!");
1379 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1380 }
1381
Jim Grosbach89df9962011-08-26 21:43:41 +00001382 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1383 assert(N == 1 && "Invalid number of operands!");
1384 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1385 }
1386
1387 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1388 assert(N == 1 && "Invalid number of operands!");
1389 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1390 }
1391
Jim Grosbachd67641b2010-12-06 18:21:12 +00001392 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1393 assert(N == 1 && "Invalid number of operands!");
1394 Inst.addOperand(MCOperand::CreateReg(getReg()));
1395 }
1396
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001397 void addRegOperands(MCInst &Inst, unsigned N) const {
1398 assert(N == 1 && "Invalid number of operands!");
1399 Inst.addOperand(MCOperand::CreateReg(getReg()));
1400 }
1401
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001402 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001403 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001404 assert(isRegShiftedReg() &&
1405 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001406 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1407 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001408 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001409 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001410 }
1411
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001412 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001413 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001414 assert(isRegShiftedImm() &&
1415 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001416 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001417 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001418 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001419 }
1420
Jim Grosbach580f4a92011-07-25 22:20:28 +00001421 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001422 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001423 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1424 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001425 }
1426
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001427 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001428 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001429 const SmallVectorImpl<unsigned> &RegList = getRegList();
1430 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001431 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1432 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001433 }
1434
Bill Wendling0f630752010-11-17 04:32:08 +00001435 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1436 addRegListOperands(Inst, N);
1437 }
1438
1439 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1440 addRegListOperands(Inst, N);
1441 }
1442
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001443 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1444 assert(N == 1 && "Invalid number of operands!");
1445 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1446 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1447 }
1448
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001449 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1450 assert(N == 1 && "Invalid number of operands!");
1451 // Munge the lsb/width into a bitfield mask.
1452 unsigned lsb = Bitfield.LSB;
1453 unsigned width = Bitfield.Width;
1454 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1455 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1456 (32 - (lsb + width)));
1457 Inst.addOperand(MCOperand::CreateImm(Mask));
1458 }
1459
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001460 void addImmOperands(MCInst &Inst, unsigned N) const {
1461 assert(N == 1 && "Invalid number of operands!");
1462 addExpr(Inst, getImm());
1463 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001464
Jim Grosbach4050bc42011-12-22 22:19:05 +00001465 void addFBits16Operands(MCInst &Inst, unsigned N) const {
1466 assert(N == 1 && "Invalid number of operands!");
1467 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1468 Inst.addOperand(MCOperand::CreateImm(16 - CE->getValue()));
1469 }
1470
1471 void addFBits32Operands(MCInst &Inst, unsigned N) const {
1472 assert(N == 1 && "Invalid number of operands!");
1473 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1474 Inst.addOperand(MCOperand::CreateImm(32 - CE->getValue()));
1475 }
1476
Jim Grosbach9d390362011-10-03 23:38:36 +00001477 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1478 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach51222d12012-01-20 18:09:51 +00001479 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1480 int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
1481 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach9d390362011-10-03 23:38:36 +00001482 }
1483
Jim Grosbacha77295d2011-09-08 22:07:06 +00001484 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1485 assert(N == 1 && "Invalid number of operands!");
1486 // FIXME: We really want to scale the value here, but the LDRD/STRD
1487 // instruction don't encode operands that way yet.
1488 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1489 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1490 }
1491
Jim Grosbach72f39f82011-08-24 21:22:15 +00001492 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1493 assert(N == 1 && "Invalid number of operands!");
1494 // The immediate is scaled by four in the encoding and is stored
1495 // in the MCInst as such. Lop off the low two bits here.
1496 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1497 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1498 }
1499
1500 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1501 assert(N == 1 && "Invalid number of operands!");
1502 // The immediate is scaled by four in the encoding and is stored
1503 // in the MCInst as such. Lop off the low two bits here.
1504 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1505 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1506 }
1507
Jim Grosbachf4943352011-07-25 23:09:14 +00001508 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1509 assert(N == 1 && "Invalid number of operands!");
1510 // The constant encodes as the immediate-1, and we store in the instruction
1511 // the bits as encoded, so subtract off one here.
1512 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1513 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1514 }
1515
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001516 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1517 assert(N == 1 && "Invalid number of operands!");
1518 // The constant encodes as the immediate-1, and we store in the instruction
1519 // the bits as encoded, so subtract off one here.
1520 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1521 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1522 }
1523
Jim Grosbach70939ee2011-08-17 21:51:27 +00001524 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1525 assert(N == 1 && "Invalid number of operands!");
1526 // The constant encodes as the immediate, except for 32, which encodes as
1527 // zero.
1528 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1529 unsigned Imm = CE->getValue();
1530 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1531 }
1532
Jim Grosbachf6c05252011-07-21 17:23:04 +00001533 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1534 assert(N == 1 && "Invalid number of operands!");
1535 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1536 // the instruction as well.
1537 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1538 int Val = CE->getValue();
1539 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1540 }
1541
Jim Grosbach89a63372011-10-28 22:36:30 +00001542 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1543 assert(N == 1 && "Invalid number of operands!");
1544 // The operand is actually a t2_so_imm, but we have its bitwise
1545 // negation in the assembly source, so twiddle it here.
1546 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1547 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1548 }
1549
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001550 void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1551 assert(N == 1 && "Invalid number of operands!");
1552 // The operand is actually a t2_so_imm, but we have its
1553 // negation in the assembly source, so twiddle it here.
1554 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1555 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1556 }
1557
Jim Grosbache70ec842011-10-28 22:50:54 +00001558 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1559 assert(N == 1 && "Invalid number of operands!");
1560 // The operand is actually a so_imm, but we have its bitwise
1561 // negation in the assembly source, so twiddle it here.
1562 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1563 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1564 }
1565
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001566 void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
1567 assert(N == 1 && "Invalid number of operands!");
1568 // The operand is actually a so_imm, but we have its
1569 // negation in the assembly source, so twiddle it here.
1570 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1571 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1572 }
1573
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001574 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1575 assert(N == 1 && "Invalid number of operands!");
1576 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1577 }
1578
Jim Grosbach7ce05792011-08-03 23:50:40 +00001579 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1580 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001581 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001582 }
1583
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001584 void addMemPCRelImm12Operands(MCInst &Inst, unsigned N) const {
1585 assert(N == 1 && "Invalid number of operands!");
1586 int32_t Imm = Memory.OffsetImm->getValue();
1587 // FIXME: Handle #-0
1588 if (Imm == INT32_MIN) Imm = 0;
1589 Inst.addOperand(MCOperand::CreateImm(Imm));
1590 }
1591
Jim Grosbach57dcb852011-10-11 17:29:55 +00001592 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1593 assert(N == 2 && "Invalid number of operands!");
1594 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1595 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1596 }
1597
Jim Grosbach7ce05792011-08-03 23:50:40 +00001598 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1599 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001600 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1601 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001602 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1603 // Special case for #-0
1604 if (Val == INT32_MIN) Val = 0;
1605 if (Val < 0) Val = -Val;
1606 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1607 } else {
1608 // For register offset, we encode the shift type and negation flag
1609 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001610 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1611 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001612 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001613 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1614 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001615 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001616 }
1617
Jim Grosbach039c2e12011-08-04 23:01:30 +00001618 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1619 assert(N == 2 && "Invalid number of operands!");
1620 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1621 assert(CE && "non-constant AM2OffsetImm operand!");
1622 int32_t Val = CE->getValue();
1623 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1624 // Special case for #-0
1625 if (Val == INT32_MIN) Val = 0;
1626 if (Val < 0) Val = -Val;
1627 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1628 Inst.addOperand(MCOperand::CreateReg(0));
1629 Inst.addOperand(MCOperand::CreateImm(Val));
1630 }
1631
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001632 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1633 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001634 // If we have an immediate that's not a constant, treat it as a label
1635 // reference needing a fixup. If it is a constant, it's something else
1636 // and we reject it.
1637 if (isImm()) {
1638 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1639 Inst.addOperand(MCOperand::CreateReg(0));
1640 Inst.addOperand(MCOperand::CreateImm(0));
1641 return;
1642 }
1643
Jim Grosbache53c87b2011-10-11 15:59:20 +00001644 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1645 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001646 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1647 // Special case for #-0
1648 if (Val == INT32_MIN) Val = 0;
1649 if (Val < 0) Val = -Val;
1650 Val = ARM_AM::getAM3Opc(AddSub, Val);
1651 } else {
1652 // For register offset, we encode the shift type and negation flag
1653 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001654 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001655 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001656 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1657 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001658 Inst.addOperand(MCOperand::CreateImm(Val));
1659 }
1660
1661 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1662 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001663 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001664 int32_t Val =
1665 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1666 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1667 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001668 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001669 }
1670
1671 // Constant offset.
1672 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1673 int32_t Val = CE->getValue();
1674 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1675 // Special case for #-0
1676 if (Val == INT32_MIN) Val = 0;
1677 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001678 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001679 Inst.addOperand(MCOperand::CreateReg(0));
1680 Inst.addOperand(MCOperand::CreateImm(Val));
1681 }
1682
Jim Grosbach7ce05792011-08-03 23:50:40 +00001683 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1684 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach681460f2011-11-01 01:24:45 +00001685 // If we have an immediate that's not a constant, treat it as a label
1686 // reference needing a fixup. If it is a constant, it's something else
1687 // and we reject it.
1688 if (isImm()) {
1689 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1690 Inst.addOperand(MCOperand::CreateImm(0));
1691 return;
1692 }
1693
Jim Grosbach7ce05792011-08-03 23:50:40 +00001694 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001695 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001696 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1697 // Special case for #-0
1698 if (Val == INT32_MIN) Val = 0;
1699 if (Val < 0) Val = -Val;
1700 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001701 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001702 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001703 }
1704
Jim Grosbacha77295d2011-09-08 22:07:06 +00001705 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1706 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001707 // If we have an immediate that's not a constant, treat it as a label
1708 // reference needing a fixup. If it is a constant, it's something else
1709 // and we reject it.
1710 if (isImm()) {
1711 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1712 Inst.addOperand(MCOperand::CreateImm(0));
1713 return;
1714 }
1715
Jim Grosbache53c87b2011-10-11 15:59:20 +00001716 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1717 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001718 Inst.addOperand(MCOperand::CreateImm(Val));
1719 }
1720
Jim Grosbachb6aed502011-09-09 18:37:27 +00001721 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1722 assert(N == 2 && "Invalid number of operands!");
1723 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001724 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1725 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001726 Inst.addOperand(MCOperand::CreateImm(Val));
1727 }
1728
Jim Grosbach7ce05792011-08-03 23:50:40 +00001729 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1730 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001731 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1732 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001733 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001734 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001735
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001736 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1737 addMemImm8OffsetOperands(Inst, N);
1738 }
1739
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001740 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001741 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001742 }
1743
1744 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1745 assert(N == 2 && "Invalid number of operands!");
1746 // If this is an immediate, it's a label reference.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001747 if (isImm()) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001748 addExpr(Inst, getImm());
1749 Inst.addOperand(MCOperand::CreateImm(0));
1750 return;
1751 }
1752
1753 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001754 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1755 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001756 Inst.addOperand(MCOperand::CreateImm(Val));
1757 }
1758
Jim Grosbach7ce05792011-08-03 23:50:40 +00001759 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1760 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001761 // If this is an immediate, it's a label reference.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001762 if (isImm()) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001763 addExpr(Inst, getImm());
1764 Inst.addOperand(MCOperand::CreateImm(0));
1765 return;
1766 }
1767
1768 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001769 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1770 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001771 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001772 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001773
Jim Grosbach7f739be2011-09-19 22:21:13 +00001774 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1775 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001776 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1777 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001778 }
1779
1780 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1781 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001782 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1783 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001784 }
1785
Jim Grosbach7ce05792011-08-03 23:50:40 +00001786 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1787 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001788 unsigned Val =
1789 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1790 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001791 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1792 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001793 Inst.addOperand(MCOperand::CreateImm(Val));
1794 }
1795
Jim Grosbachab899c12011-09-07 23:10:15 +00001796 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1797 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001798 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1799 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1800 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001801 }
1802
Jim Grosbach7ce05792011-08-03 23:50:40 +00001803 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1804 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001805 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1806 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001807 }
1808
Jim Grosbach60f91a32011-08-19 17:55:24 +00001809 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1810 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001811 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1812 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001813 Inst.addOperand(MCOperand::CreateImm(Val));
1814 }
1815
Jim Grosbach38466302011-08-19 18:55:51 +00001816 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1817 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001818 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1819 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001820 Inst.addOperand(MCOperand::CreateImm(Val));
1821 }
1822
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001823 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1824 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001825 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1826 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001827 Inst.addOperand(MCOperand::CreateImm(Val));
1828 }
1829
Jim Grosbachecd85892011-08-19 18:13:48 +00001830 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1831 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001832 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1833 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001834 Inst.addOperand(MCOperand::CreateImm(Val));
1835 }
1836
Jim Grosbach7ce05792011-08-03 23:50:40 +00001837 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1838 assert(N == 1 && "Invalid number of operands!");
1839 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1840 assert(CE && "non-constant post-idx-imm8 operand!");
1841 int Imm = CE->getValue();
1842 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001843 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001844 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1845 Inst.addOperand(MCOperand::CreateImm(Imm));
1846 }
1847
Jim Grosbach2bd01182011-10-11 21:55:36 +00001848 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1849 assert(N == 1 && "Invalid number of operands!");
1850 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1851 assert(CE && "non-constant post-idx-imm8s4 operand!");
1852 int Imm = CE->getValue();
1853 bool isAdd = Imm >= 0;
1854 if (Imm == INT32_MIN) Imm = 0;
1855 // Immediate is scaled by 4.
1856 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1857 Inst.addOperand(MCOperand::CreateImm(Imm));
1858 }
1859
Jim Grosbach7ce05792011-08-03 23:50:40 +00001860 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1861 assert(N == 2 && "Invalid number of operands!");
1862 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001863 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1864 }
1865
1866 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1867 assert(N == 2 && "Invalid number of operands!");
1868 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1869 // The sign, shift type, and shift amount are encoded in a single operand
1870 // using the AM2 encoding helpers.
1871 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1872 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1873 PostIdxReg.ShiftTy);
1874 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001875 }
1876
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001877 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1878 assert(N == 1 && "Invalid number of operands!");
1879 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1880 }
1881
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001882 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1883 assert(N == 1 && "Invalid number of operands!");
1884 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1885 }
1886
Jim Grosbach6029b6d2011-11-29 23:51:09 +00001887 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach862019c2011-10-18 23:02:30 +00001888 assert(N == 1 && "Invalid number of operands!");
1889 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1890 }
1891
Jim Grosbach7636bf62011-12-02 00:35:16 +00001892 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1893 assert(N == 2 && "Invalid number of operands!");
1894 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1895 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1896 }
1897
Jim Grosbach460a9052011-10-07 23:56:00 +00001898 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1899 assert(N == 1 && "Invalid number of operands!");
1900 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1901 }
1902
1903 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1904 assert(N == 1 && "Invalid number of operands!");
1905 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1906 }
1907
1908 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1909 assert(N == 1 && "Invalid number of operands!");
1910 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1911 }
1912
Jim Grosbach0e387b22011-10-17 22:26:03 +00001913 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1914 assert(N == 1 && "Invalid number of operands!");
1915 // The immediate encodes the type of constant as well as the value.
1916 // Mask in that this is an i8 splat.
1917 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1918 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1919 }
1920
Jim Grosbachea461102011-10-17 23:09:09 +00001921 void addNEONi16splatOperands(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 unsigned Value = CE->getValue();
1926 if (Value >= 256)
1927 Value = (Value >> 8) | 0xa00;
1928 else
1929 Value |= 0x800;
1930 Inst.addOperand(MCOperand::CreateImm(Value));
1931 }
1932
Jim Grosbach6248a542011-10-18 00:22:00 +00001933 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1934 assert(N == 1 && "Invalid number of operands!");
1935 // The immediate encodes the type of constant as well as the value.
1936 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1937 unsigned Value = CE->getValue();
1938 if (Value >= 256 && Value <= 0xff00)
1939 Value = (Value >> 8) | 0x200;
1940 else if (Value > 0xffff && Value <= 0xff0000)
1941 Value = (Value >> 16) | 0x400;
1942 else if (Value > 0xffffff)
1943 Value = (Value >> 24) | 0x600;
1944 Inst.addOperand(MCOperand::CreateImm(Value));
1945 }
1946
1947 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1948 assert(N == 1 && "Invalid number of operands!");
1949 // The immediate encodes the type of constant as well as the value.
1950 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1951 unsigned Value = CE->getValue();
1952 if (Value >= 256 && Value <= 0xffff)
1953 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1954 else if (Value > 0xffff && Value <= 0xffffff)
1955 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1956 else if (Value > 0xffffff)
1957 Value = (Value >> 24) | 0x600;
1958 Inst.addOperand(MCOperand::CreateImm(Value));
1959 }
1960
Jim Grosbach9b087852011-12-19 23:51:07 +00001961 void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const {
1962 assert(N == 1 && "Invalid number of operands!");
1963 // The immediate encodes the type of constant as well as the value.
1964 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1965 unsigned Value = ~CE->getValue();
1966 if (Value >= 256 && Value <= 0xffff)
1967 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1968 else if (Value > 0xffff && Value <= 0xffffff)
1969 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1970 else if (Value > 0xffffff)
1971 Value = (Value >> 24) | 0x600;
1972 Inst.addOperand(MCOperand::CreateImm(Value));
1973 }
1974
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001975 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1976 assert(N == 1 && "Invalid number of operands!");
1977 // The immediate encodes the type of constant as well as the value.
1978 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1979 uint64_t Value = CE->getValue();
1980 unsigned Imm = 0;
1981 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1982 Imm |= (Value & 1) << i;
1983 }
1984 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1985 }
1986
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001987 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001988
Jim Grosbach89df9962011-08-26 21:43:41 +00001989 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001990 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001991 Op->ITMask.Mask = Mask;
1992 Op->StartLoc = S;
1993 Op->EndLoc = S;
1994 return Op;
1995 }
1996
Chris Lattner3a697562010-10-28 17:20:03 +00001997 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001998 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001999 Op->CC.Val = CC;
2000 Op->StartLoc = S;
2001 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00002002 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00002003 }
2004
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002005 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002006 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002007 Op->Cop.Val = CopVal;
2008 Op->StartLoc = S;
2009 Op->EndLoc = S;
2010 return Op;
2011 }
2012
2013 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002014 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002015 Op->Cop.Val = CopVal;
2016 Op->StartLoc = S;
2017 Op->EndLoc = S;
2018 return Op;
2019 }
2020
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002021 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
2022 ARMOperand *Op = new ARMOperand(k_CoprocOption);
2023 Op->Cop.Val = Val;
2024 Op->StartLoc = S;
2025 Op->EndLoc = E;
2026 return Op;
2027 }
2028
Jim Grosbachd67641b2010-12-06 18:21:12 +00002029 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002030 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00002031 Op->Reg.RegNum = RegNum;
2032 Op->StartLoc = S;
2033 Op->EndLoc = S;
2034 return Op;
2035 }
2036
Chris Lattner3a697562010-10-28 17:20:03 +00002037 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002038 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00002039 Op->Tok.Data = Str.data();
2040 Op->Tok.Length = Str.size();
2041 Op->StartLoc = S;
2042 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00002043 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002044 }
2045
Bill Wendling50d0f582010-11-18 23:43:05 +00002046 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002047 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00002048 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00002049 Op->StartLoc = S;
2050 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002051 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002052 }
2053
Jim Grosbache8606dc2011-07-13 17:50:29 +00002054 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
2055 unsigned SrcReg,
2056 unsigned ShiftReg,
2057 unsigned ShiftImm,
2058 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002059 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002060 Op->RegShiftedReg.ShiftTy = ShTy;
2061 Op->RegShiftedReg.SrcReg = SrcReg;
2062 Op->RegShiftedReg.ShiftReg = ShiftReg;
2063 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002064 Op->StartLoc = S;
2065 Op->EndLoc = E;
2066 return Op;
2067 }
2068
Owen Anderson92a20222011-07-21 18:54:16 +00002069 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
2070 unsigned SrcReg,
2071 unsigned ShiftImm,
2072 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002073 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002074 Op->RegShiftedImm.ShiftTy = ShTy;
2075 Op->RegShiftedImm.SrcReg = SrcReg;
2076 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00002077 Op->StartLoc = S;
2078 Op->EndLoc = E;
2079 return Op;
2080 }
2081
Jim Grosbach580f4a92011-07-25 22:20:28 +00002082 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002083 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002084 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00002085 Op->ShifterImm.isASR = isASR;
2086 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00002087 Op->StartLoc = S;
2088 Op->EndLoc = E;
2089 return Op;
2090 }
2091
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002092 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002093 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002094 Op->RotImm.Imm = Imm;
2095 Op->StartLoc = S;
2096 Op->EndLoc = E;
2097 return Op;
2098 }
2099
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002100 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
2101 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002102 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002103 Op->Bitfield.LSB = LSB;
2104 Op->Bitfield.Width = Width;
2105 Op->StartLoc = S;
2106 Op->EndLoc = E;
2107 return Op;
2108 }
2109
Bill Wendling7729e062010-11-09 22:44:22 +00002110 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00002111 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002112 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002113 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002114
Jim Grosbachd300b942011-09-13 22:56:44 +00002115 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002116 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00002117 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00002118 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002119 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002120
2121 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00002122 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002123 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00002124 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00002125 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002126 Op->StartLoc = StartLoc;
2127 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00002128 return Op;
2129 }
2130
Jim Grosbach862019c2011-10-18 23:02:30 +00002131 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002132 bool isDoubleSpaced, SMLoc S, SMLoc E) {
Jim Grosbach862019c2011-10-18 23:02:30 +00002133 ARMOperand *Op = new ARMOperand(k_VectorList);
2134 Op->VectorList.RegNum = RegNum;
2135 Op->VectorList.Count = Count;
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002136 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach862019c2011-10-18 23:02:30 +00002137 Op->StartLoc = S;
2138 Op->EndLoc = E;
2139 return Op;
2140 }
2141
Jim Grosbach98b05a52011-11-30 01:09:44 +00002142 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002143 bool isDoubleSpaced,
Jim Grosbach98b05a52011-11-30 01:09:44 +00002144 SMLoc S, SMLoc E) {
2145 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
2146 Op->VectorList.RegNum = RegNum;
2147 Op->VectorList.Count = Count;
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002148 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002149 Op->StartLoc = S;
2150 Op->EndLoc = E;
2151 return Op;
2152 }
2153
Jim Grosbach7636bf62011-12-02 00:35:16 +00002154 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002155 unsigned Index,
2156 bool isDoubleSpaced,
2157 SMLoc S, SMLoc E) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002158 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
2159 Op->VectorList.RegNum = RegNum;
2160 Op->VectorList.Count = Count;
2161 Op->VectorList.LaneIndex = Index;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002162 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002163 Op->StartLoc = S;
2164 Op->EndLoc = E;
2165 return Op;
2166 }
2167
Jim Grosbach460a9052011-10-07 23:56:00 +00002168 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
2169 MCContext &Ctx) {
2170 ARMOperand *Op = new ARMOperand(k_VectorIndex);
2171 Op->VectorIndex.Val = Idx;
2172 Op->StartLoc = S;
2173 Op->EndLoc = E;
2174 return Op;
2175 }
2176
Chris Lattner3a697562010-10-28 17:20:03 +00002177 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002178 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00002179 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00002180 Op->StartLoc = S;
2181 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002182 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00002183 }
2184
Jim Grosbach7ce05792011-08-03 23:50:40 +00002185 static ARMOperand *CreateMem(unsigned BaseRegNum,
2186 const MCConstantExpr *OffsetImm,
2187 unsigned OffsetRegNum,
2188 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002189 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00002190 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002191 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00002192 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002193 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00002194 Op->Memory.BaseRegNum = BaseRegNum;
2195 Op->Memory.OffsetImm = OffsetImm;
2196 Op->Memory.OffsetRegNum = OffsetRegNum;
2197 Op->Memory.ShiftType = ShiftType;
2198 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00002199 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00002200 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002201 Op->StartLoc = S;
2202 Op->EndLoc = E;
2203 return Op;
2204 }
Jim Grosbach16c74252010-10-29 14:46:02 +00002205
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002206 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
2207 ARM_AM::ShiftOpc ShiftTy,
2208 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002209 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002210 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002211 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002212 Op->PostIdxReg.isAdd = isAdd;
2213 Op->PostIdxReg.ShiftTy = ShiftTy;
2214 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00002215 Op->StartLoc = S;
2216 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002217 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002218 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002219
2220 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002221 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002222 Op->MBOpt.Val = Opt;
2223 Op->StartLoc = S;
2224 Op->EndLoc = S;
2225 return Op;
2226 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002227
2228 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002229 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002230 Op->IFlags.Val = IFlags;
2231 Op->StartLoc = S;
2232 Op->EndLoc = S;
2233 return Op;
2234 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002235
2236 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002237 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002238 Op->MMask.Val = MMask;
2239 Op->StartLoc = S;
2240 Op->EndLoc = S;
2241 return Op;
2242 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002243};
2244
2245} // end anonymous namespace.
2246
Jim Grosbachb7f689b2011-07-13 15:34:57 +00002247void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002248 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002249 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00002250 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002251 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002252 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00002253 OS << "<ccout " << getReg() << ">";
2254 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002255 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002256 static const char *MaskStr[] = {
2257 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2258 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2259 };
Jim Grosbach89df9962011-08-26 21:43:41 +00002260 assert((ITMask.Mask & 0xf) == ITMask.Mask);
2261 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2262 break;
2263 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002264 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002265 OS << "<coprocessor number: " << getCoproc() << ">";
2266 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002267 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002268 OS << "<coprocessor register: " << getCoproc() << ">";
2269 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002270 case k_CoprocOption:
2271 OS << "<coprocessor option: " << CoprocOption.Val << ">";
2272 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002273 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002274 OS << "<mask: " << getMSRMask() << ">";
2275 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002276 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002277 getImm()->print(OS);
2278 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002279 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002280 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2281 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002282 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002283 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00002284 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002285 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002286 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002287 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002288 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2289 << PostIdxReg.RegNum;
2290 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2291 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2292 << PostIdxReg.ShiftImm;
2293 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00002294 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002295 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002296 OS << "<ARM_PROC::";
2297 unsigned IFlags = getProcIFlags();
2298 for (int i=2; i >= 0; --i)
2299 if (IFlags & (1 << i))
2300 OS << ARM_PROC::IFlagsToString(1 << i);
2301 OS << ">";
2302 break;
2303 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002304 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00002305 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002306 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002307 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00002308 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2309 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00002310 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002311 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00002312 OS << "<so_reg_reg "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002313 << RegShiftedReg.SrcReg << " "
2314 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2315 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson00828302011-03-18 22:50:18 +00002316 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002317 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00002318 OS << "<so_reg_imm "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002319 << RegShiftedImm.SrcReg << " "
2320 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2321 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Anderson92a20222011-07-21 18:54:16 +00002322 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002323 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002324 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2325 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002326 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002327 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2328 << ", width: " << Bitfield.Width << ">";
2329 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002330 case k_RegisterList:
2331 case k_DPRRegisterList:
2332 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00002333 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002334
Bill Wendling5fa22a12010-11-09 23:28:44 +00002335 const SmallVectorImpl<unsigned> &RegList = getRegList();
2336 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002337 I = RegList.begin(), E = RegList.end(); I != E; ) {
2338 OS << *I;
2339 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002340 }
2341
2342 OS << ">";
2343 break;
2344 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002345 case k_VectorList:
2346 OS << "<vector_list " << VectorList.Count << " * "
2347 << VectorList.RegNum << ">";
2348 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002349 case k_VectorListAllLanes:
2350 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2351 << VectorList.RegNum << ">";
2352 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002353 case k_VectorListIndexed:
2354 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2355 << VectorList.Count << " * " << VectorList.RegNum << ">";
2356 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002357 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002358 OS << "'" << getToken() << "'";
2359 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00002360 case k_VectorIndex:
2361 OS << "<vectorindex " << getVectorIndex() << ">";
2362 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002363 }
2364}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00002365
2366/// @name Auto-generated Match Functions
2367/// {
2368
2369static unsigned MatchRegisterName(StringRef Name);
2370
2371/// }
2372
Bob Wilson69df7232011-02-03 21:46:10 +00002373bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2374 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbacha39cda72011-12-14 02:16:11 +00002375 StartLoc = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002376 RegNo = tryParseRegister();
Jim Grosbacha39cda72011-12-14 02:16:11 +00002377 EndLoc = Parser.getTok().getLoc();
Roman Divackybf755322011-01-27 17:14:22 +00002378
2379 return (RegNo == (unsigned)-1);
2380}
2381
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002382/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002383/// and if it is a register name the token is eaten and the register number is
2384/// returned. Otherwise return -1.
2385///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002386int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002387 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002388 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002389
Benjamin Kramer59085362011-11-06 20:37:06 +00002390 std::string lowerCase = Tok.getString().lower();
Owen Anderson0c9f2502011-01-13 22:50:36 +00002391 unsigned RegNum = MatchRegisterName(lowerCase);
2392 if (!RegNum) {
2393 RegNum = StringSwitch<unsigned>(lowerCase)
2394 .Case("r13", ARM::SP)
2395 .Case("r14", ARM::LR)
2396 .Case("r15", ARM::PC)
2397 .Case("ip", ARM::R12)
Jim Grosbach40e28552011-12-08 19:27:38 +00002398 // Additional register name aliases for 'gas' compatibility.
2399 .Case("a1", ARM::R0)
2400 .Case("a2", ARM::R1)
2401 .Case("a3", ARM::R2)
2402 .Case("a4", ARM::R3)
2403 .Case("v1", ARM::R4)
2404 .Case("v2", ARM::R5)
2405 .Case("v3", ARM::R6)
2406 .Case("v4", ARM::R7)
2407 .Case("v5", ARM::R8)
2408 .Case("v6", ARM::R9)
2409 .Case("v7", ARM::R10)
2410 .Case("v8", ARM::R11)
2411 .Case("sb", ARM::R9)
2412 .Case("sl", ARM::R10)
2413 .Case("fp", ARM::R11)
Owen Anderson0c9f2502011-01-13 22:50:36 +00002414 .Default(0);
2415 }
Jim Grosbacha39cda72011-12-14 02:16:11 +00002416 if (!RegNum) {
Jim Grosbachaee718b2011-12-20 23:11:00 +00002417 // Check for aliases registered via .req. Canonicalize to lower case.
2418 // That's more consistent since register names are case insensitive, and
2419 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2420 StringMap<unsigned>::const_iterator Entry = RegisterReqs.find(lowerCase);
Jim Grosbacha39cda72011-12-14 02:16:11 +00002421 // If no match, return failure.
2422 if (Entry == RegisterReqs.end())
2423 return -1;
2424 Parser.Lex(); // Eat identifier token.
2425 return Entry->getValue();
2426 }
Bob Wilson69df7232011-02-03 21:46:10 +00002427
Chris Lattnere5658fa2010-10-30 04:09:10 +00002428 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002429
Chris Lattnere5658fa2010-10-30 04:09:10 +00002430 return RegNum;
2431}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002432
Jim Grosbach19906722011-07-13 18:49:30 +00002433// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2434// If a recoverable error occurs, return 1. If an irrecoverable error
2435// occurs, return -1. An irrecoverable error is one where tokens have been
2436// consumed in the process of trying to parse the shifter (i.e., when it is
2437// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002438int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002439 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2440 SMLoc S = Parser.getTok().getLoc();
2441 const AsmToken &Tok = Parser.getTok();
2442 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2443
Benjamin Kramer59085362011-11-06 20:37:06 +00002444 std::string lowerCase = Tok.getString().lower();
Owen Anderson00828302011-03-18 22:50:18 +00002445 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbachaf4edea2011-12-07 23:40:58 +00002446 .Case("asl", ARM_AM::lsl)
Owen Anderson00828302011-03-18 22:50:18 +00002447 .Case("lsl", ARM_AM::lsl)
2448 .Case("lsr", ARM_AM::lsr)
2449 .Case("asr", ARM_AM::asr)
2450 .Case("ror", ARM_AM::ror)
2451 .Case("rrx", ARM_AM::rrx)
2452 .Default(ARM_AM::no_shift);
2453
2454 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002455 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002456
Jim Grosbache8606dc2011-07-13 17:50:29 +00002457 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002458
Jim Grosbache8606dc2011-07-13 17:50:29 +00002459 // The source register for the shift has already been added to the
2460 // operand list, so we need to pop it off and combine it into the shifted
2461 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002462 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002463 if (!PrevOp->isReg())
2464 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2465 int SrcReg = PrevOp->getReg();
2466 int64_t Imm = 0;
2467 int ShiftReg = 0;
2468 if (ShiftTy == ARM_AM::rrx) {
2469 // RRX Doesn't have an explicit shift amount. The encoder expects
2470 // the shift register to be the same as the source register. Seems odd,
2471 // but OK.
2472 ShiftReg = SrcReg;
2473 } else {
2474 // Figure out if this is shifted by a constant or a register (for non-RRX).
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00002475 if (Parser.getTok().is(AsmToken::Hash) ||
2476 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbache8606dc2011-07-13 17:50:29 +00002477 Parser.Lex(); // Eat hash.
2478 SMLoc ImmLoc = Parser.getTok().getLoc();
2479 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002480 if (getParser().ParseExpression(ShiftExpr)) {
2481 Error(ImmLoc, "invalid immediate shift value");
2482 return -1;
2483 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002484 // The expression must be evaluatable as an immediate.
2485 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002486 if (!CE) {
2487 Error(ImmLoc, "invalid immediate shift value");
2488 return -1;
2489 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002490 // Range check the immediate.
2491 // lsl, ror: 0 <= imm <= 31
2492 // lsr, asr: 0 <= imm <= 32
2493 Imm = CE->getValue();
2494 if (Imm < 0 ||
2495 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2496 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002497 Error(ImmLoc, "immediate shift value out of range");
2498 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002499 }
Jim Grosbachde626ad2011-12-22 17:37:00 +00002500 // shift by zero is a nop. Always send it through as lsl.
2501 // ('as' compatibility)
2502 if (Imm == 0)
2503 ShiftTy = ARM_AM::lsl;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002504 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002505 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002506 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002507 if (ShiftReg == -1) {
2508 Error (L, "expected immediate or register in shift operand");
2509 return -1;
2510 }
2511 } else {
2512 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002513 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002514 return -1;
2515 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002516 }
2517
Owen Anderson92a20222011-07-21 18:54:16 +00002518 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2519 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002520 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002521 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002522 else
2523 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2524 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002525
Jim Grosbach19906722011-07-13 18:49:30 +00002526 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002527}
2528
2529
Bill Wendling50d0f582010-11-18 23:43:05 +00002530/// Try to parse a register name. The token must be an Identifier when called.
2531/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2532/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002533///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002534/// TODO this is likely to change to allow different register types and or to
2535/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002536bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002537tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002538 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002539 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002540 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002541 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002542
Bill Wendling50d0f582010-11-18 23:43:05 +00002543 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002544
Chris Lattnere5658fa2010-10-30 04:09:10 +00002545 const AsmToken &ExclaimTok = Parser.getTok();
2546 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002547 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2548 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002549 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002550 return false;
2551 }
2552
2553 // Also check for an index operand. This is only legal for vector registers,
2554 // but that'll get caught OK in operand matching, so we don't need to
2555 // explicitly filter everything else out here.
2556 if (Parser.getTok().is(AsmToken::LBrac)) {
2557 SMLoc SIdx = Parser.getTok().getLoc();
2558 Parser.Lex(); // Eat left bracket token.
2559
2560 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002561 if (getParser().ParseExpression(ImmVal))
Jim Grosbach24dda212012-01-31 23:51:09 +00002562 return true;
Jim Grosbach460a9052011-10-07 23:56:00 +00002563 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbachef4d3eb2012-01-26 15:56:45 +00002564 if (!MCE)
2565 return TokError("immediate value expected for vector index");
Jim Grosbach460a9052011-10-07 23:56:00 +00002566
2567 SMLoc E = Parser.getTok().getLoc();
Jim Grosbachef4d3eb2012-01-26 15:56:45 +00002568 if (Parser.getTok().isNot(AsmToken::RBrac))
2569 return Error(E, "']' expected");
Jim Grosbach460a9052011-10-07 23:56:00 +00002570
2571 Parser.Lex(); // Eat right bracket token.
2572
2573 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2574 SIdx, E,
2575 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002576 }
2577
Bill Wendling50d0f582010-11-18 23:43:05 +00002578 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002579}
2580
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002581/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2582/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2583/// "c5", ...
2584static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002585 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2586 // but efficient.
2587 switch (Name.size()) {
David Blaikie4d6ccb52012-01-20 21:51:11 +00002588 default: return -1;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002589 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002590 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002591 return -1;
2592 switch (Name[1]) {
2593 default: return -1;
2594 case '0': return 0;
2595 case '1': return 1;
2596 case '2': return 2;
2597 case '3': return 3;
2598 case '4': return 4;
2599 case '5': return 5;
2600 case '6': return 6;
2601 case '7': return 7;
2602 case '8': return 8;
2603 case '9': return 9;
2604 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002605 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002606 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002607 return -1;
2608 switch (Name[2]) {
2609 default: return -1;
2610 case '0': return 10;
2611 case '1': return 11;
2612 case '2': return 12;
2613 case '3': return 13;
2614 case '4': return 14;
2615 case '5': return 15;
2616 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002617 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002618}
2619
Jim Grosbach89df9962011-08-26 21:43:41 +00002620/// parseITCondCode - Try to parse a condition code for an IT instruction.
2621ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2622parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2623 SMLoc S = Parser.getTok().getLoc();
2624 const AsmToken &Tok = Parser.getTok();
2625 if (!Tok.is(AsmToken::Identifier))
2626 return MatchOperand_NoMatch;
2627 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2628 .Case("eq", ARMCC::EQ)
2629 .Case("ne", ARMCC::NE)
2630 .Case("hs", ARMCC::HS)
2631 .Case("cs", ARMCC::HS)
2632 .Case("lo", ARMCC::LO)
2633 .Case("cc", ARMCC::LO)
2634 .Case("mi", ARMCC::MI)
2635 .Case("pl", ARMCC::PL)
2636 .Case("vs", ARMCC::VS)
2637 .Case("vc", ARMCC::VC)
2638 .Case("hi", ARMCC::HI)
2639 .Case("ls", ARMCC::LS)
2640 .Case("ge", ARMCC::GE)
2641 .Case("lt", ARMCC::LT)
2642 .Case("gt", ARMCC::GT)
2643 .Case("le", ARMCC::LE)
2644 .Case("al", ARMCC::AL)
2645 .Default(~0U);
2646 if (CC == ~0U)
2647 return MatchOperand_NoMatch;
2648 Parser.Lex(); // Eat the token.
2649
2650 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2651
2652 return MatchOperand_Success;
2653}
2654
Jim Grosbach43904292011-07-25 20:14:50 +00002655/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002656/// token must be an Identifier when called, and if it is a coprocessor
2657/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002658ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002659parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002660 SMLoc S = Parser.getTok().getLoc();
2661 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002662 if (Tok.isNot(AsmToken::Identifier))
2663 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002664
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002665 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002666 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002667 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002668
2669 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002670 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002671 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002672}
2673
Jim Grosbach43904292011-07-25 20:14:50 +00002674/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002675/// token must be an Identifier when called, and if it is a coprocessor
2676/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002677ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002678parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002679 SMLoc S = Parser.getTok().getLoc();
2680 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002681 if (Tok.isNot(AsmToken::Identifier))
2682 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002683
2684 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2685 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002686 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002687
2688 Parser.Lex(); // Eat identifier token.
2689 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002690 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002691}
2692
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002693/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2694/// coproc_option : '{' imm0_255 '}'
2695ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2696parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2697 SMLoc S = Parser.getTok().getLoc();
2698
2699 // If this isn't a '{', this isn't a coprocessor immediate operand.
2700 if (Parser.getTok().isNot(AsmToken::LCurly))
2701 return MatchOperand_NoMatch;
2702 Parser.Lex(); // Eat the '{'
2703
2704 const MCExpr *Expr;
2705 SMLoc Loc = Parser.getTok().getLoc();
2706 if (getParser().ParseExpression(Expr)) {
2707 Error(Loc, "illegal expression");
2708 return MatchOperand_ParseFail;
2709 }
2710 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2711 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2712 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2713 return MatchOperand_ParseFail;
2714 }
2715 int Val = CE->getValue();
2716
2717 // Check for and consume the closing '}'
2718 if (Parser.getTok().isNot(AsmToken::RCurly))
2719 return MatchOperand_ParseFail;
2720 SMLoc E = Parser.getTok().getLoc();
2721 Parser.Lex(); // Eat the '}'
2722
2723 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2724 return MatchOperand_Success;
2725}
2726
Jim Grosbachd0588e22011-09-14 18:08:35 +00002727// For register list parsing, we need to map from raw GPR register numbering
2728// to the enumeration values. The enumeration values aren't sorted by
2729// register number due to our using "sp", "lr" and "pc" as canonical names.
2730static unsigned getNextRegister(unsigned Reg) {
2731 // If this is a GPR, we need to do it manually, otherwise we can rely
2732 // on the sort ordering of the enumeration since the other reg-classes
2733 // are sane.
2734 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2735 return Reg + 1;
2736 switch(Reg) {
Craig Topperbc219812012-02-07 02:50:20 +00002737 default: llvm_unreachable("Invalid GPR number!");
Jim Grosbachd0588e22011-09-14 18:08:35 +00002738 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2739 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2740 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2741 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2742 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2743 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2744 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2745 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2746 }
2747}
2748
Jim Grosbachce485e72011-11-11 21:27:40 +00002749// Return the low-subreg of a given Q register.
2750static unsigned getDRegFromQReg(unsigned QReg) {
2751 switch (QReg) {
2752 default: llvm_unreachable("expected a Q register!");
2753 case ARM::Q0: return ARM::D0;
2754 case ARM::Q1: return ARM::D2;
2755 case ARM::Q2: return ARM::D4;
2756 case ARM::Q3: return ARM::D6;
2757 case ARM::Q4: return ARM::D8;
2758 case ARM::Q5: return ARM::D10;
2759 case ARM::Q6: return ARM::D12;
2760 case ARM::Q7: return ARM::D14;
2761 case ARM::Q8: return ARM::D16;
Jim Grosbach25e0a872011-11-15 21:01:30 +00002762 case ARM::Q9: return ARM::D18;
Jim Grosbachce485e72011-11-11 21:27:40 +00002763 case ARM::Q10: return ARM::D20;
2764 case ARM::Q11: return ARM::D22;
2765 case ARM::Q12: return ARM::D24;
2766 case ARM::Q13: return ARM::D26;
2767 case ARM::Q14: return ARM::D28;
2768 case ARM::Q15: return ARM::D30;
2769 }
2770}
2771
Jim Grosbachd0588e22011-09-14 18:08:35 +00002772/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002773bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002774parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002775 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002776 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002777 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002778 Parser.Lex(); // Eat '{' token.
2779 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002780
Jim Grosbachd0588e22011-09-14 18:08:35 +00002781 // Check the first register in the list to see what register class
2782 // this is a list of.
2783 int Reg = tryParseRegister();
2784 if (Reg == -1)
2785 return Error(RegLoc, "register expected");
2786
Jim Grosbachce485e72011-11-11 21:27:40 +00002787 // The reglist instructions have at most 16 registers, so reserve
2788 // space for that many.
2789 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2790
2791 // Allow Q regs and just interpret them as the two D sub-registers.
2792 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2793 Reg = getDRegFromQReg(Reg);
2794 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2795 ++Reg;
2796 }
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002797 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002798 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2799 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2800 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2801 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2802 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2803 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2804 else
2805 return Error(RegLoc, "invalid register in register list");
2806
Jim Grosbachce485e72011-11-11 21:27:40 +00002807 // Store the register.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002808 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002809
Jim Grosbachd0588e22011-09-14 18:08:35 +00002810 // This starts immediately after the first register token in the list,
2811 // so we can see either a comma or a minus (range separator) as a legal
2812 // next token.
2813 while (Parser.getTok().is(AsmToken::Comma) ||
2814 Parser.getTok().is(AsmToken::Minus)) {
2815 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache43862b2011-11-15 23:19:15 +00002816 Parser.Lex(); // Eat the minus.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002817 SMLoc EndLoc = Parser.getTok().getLoc();
2818 int EndReg = tryParseRegister();
2819 if (EndReg == -1)
2820 return Error(EndLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002821 // Allow Q regs and just interpret them as the two D sub-registers.
2822 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2823 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002824 // If the register is the same as the start reg, there's nothing
2825 // more to do.
2826 if (Reg == EndReg)
2827 continue;
2828 // The register must be in the same register class as the first.
2829 if (!RC->contains(EndReg))
2830 return Error(EndLoc, "invalid register in register list");
2831 // Ranges must go from low to high.
2832 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2833 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002834
Jim Grosbachd0588e22011-09-14 18:08:35 +00002835 // Add all the registers in the range to the register list.
2836 while (Reg != EndReg) {
2837 Reg = getNextRegister(Reg);
2838 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2839 }
2840 continue;
2841 }
2842 Parser.Lex(); // Eat the comma.
2843 RegLoc = Parser.getTok().getLoc();
2844 int OldReg = Reg;
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002845 const AsmToken RegTok = Parser.getTok();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002846 Reg = tryParseRegister();
2847 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002848 return Error(RegLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002849 // Allow Q regs and just interpret them as the two D sub-registers.
2850 bool isQReg = false;
2851 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2852 Reg = getDRegFromQReg(Reg);
2853 isQReg = true;
2854 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002855 // The register must be in the same register class as the first.
2856 if (!RC->contains(Reg))
2857 return Error(RegLoc, "invalid register in register list");
2858 // List must be monotonically increasing.
Jim Grosbachbe7cf2b2012-03-16 20:48:38 +00002859 if (getARMRegisterNumbering(Reg) < getARMRegisterNumbering(OldReg)) {
2860 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2861 Warning(RegLoc, "register list not in ascending order");
2862 else
2863 return Error(RegLoc, "register list not in ascending order");
2864 }
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002865 if (getARMRegisterNumbering(Reg) == getARMRegisterNumbering(OldReg)) {
2866 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
2867 ") in register list");
2868 continue;
2869 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002870 // VFP register lists must also be contiguous.
2871 // It's OK to use the enumeration values directly here rather, as the
2872 // VFP register classes have the enum sorted properly.
2873 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2874 Reg != OldReg + 1)
2875 return Error(RegLoc, "non-contiguous register range");
2876 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbachce485e72011-11-11 21:27:40 +00002877 if (isQReg)
2878 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002879 }
2880
Jim Grosbachd0588e22011-09-14 18:08:35 +00002881 SMLoc E = Parser.getTok().getLoc();
2882 if (Parser.getTok().isNot(AsmToken::RCurly))
2883 return Error(E, "'}' expected");
2884 Parser.Lex(); // Eat '}' token.
2885
Jim Grosbach27debd62011-12-13 21:48:29 +00002886 // Push the register list operand.
Bill Wendling50d0f582010-11-18 23:43:05 +00002887 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
Jim Grosbach27debd62011-12-13 21:48:29 +00002888
2889 // The ARM system instruction variants for LDM/STM have a '^' token here.
2890 if (Parser.getTok().is(AsmToken::Caret)) {
2891 Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
2892 Parser.Lex(); // Eat '^' token.
2893 }
2894
Bill Wendling50d0f582010-11-18 23:43:05 +00002895 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002896}
2897
Jim Grosbach98b05a52011-11-30 01:09:44 +00002898// Helper function to parse the lane index for vector lists.
2899ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach7636bf62011-12-02 00:35:16 +00002900parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2901 Index = 0; // Always return a defined index value.
Jim Grosbach98b05a52011-11-30 01:09:44 +00002902 if (Parser.getTok().is(AsmToken::LBrac)) {
2903 Parser.Lex(); // Eat the '['.
2904 if (Parser.getTok().is(AsmToken::RBrac)) {
2905 // "Dn[]" is the 'all lanes' syntax.
2906 LaneKind = AllLanes;
2907 Parser.Lex(); // Eat the ']'.
2908 return MatchOperand_Success;
2909 }
Jim Grosbachceee9842012-03-19 20:39:53 +00002910
2911 // There's an optional '#' token here. Normally there wouldn't be, but
2912 // inline assemble puts one in, and it's friendly to accept that.
2913 if (Parser.getTok().is(AsmToken::Hash))
2914 Parser.Lex(); // Eat the '#'
2915
Jim Grosbachc9313252011-12-21 01:19:23 +00002916 const MCExpr *LaneIndex;
2917 SMLoc Loc = Parser.getTok().getLoc();
2918 if (getParser().ParseExpression(LaneIndex)) {
2919 Error(Loc, "illegal expression");
2920 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002921 }
Jim Grosbachc9313252011-12-21 01:19:23 +00002922 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LaneIndex);
2923 if (!CE) {
2924 Error(Loc, "lane index must be empty or an integer");
2925 return MatchOperand_ParseFail;
2926 }
2927 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2928 Error(Parser.getTok().getLoc(), "']' expected");
2929 return MatchOperand_ParseFail;
2930 }
2931 Parser.Lex(); // Eat the ']'.
2932 int64_t Val = CE->getValue();
2933
2934 // FIXME: Make this range check context sensitive for .8, .16, .32.
2935 if (Val < 0 || Val > 7) {
2936 Error(Parser.getTok().getLoc(), "lane index out of range");
2937 return MatchOperand_ParseFail;
2938 }
2939 Index = Val;
2940 LaneKind = IndexedLane;
2941 return MatchOperand_Success;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002942 }
2943 LaneKind = NoLanes;
2944 return MatchOperand_Success;
2945}
2946
Jim Grosbach862019c2011-10-18 23:02:30 +00002947// parse a vector register list
2948ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2949parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002950 VectorLaneTy LaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002951 unsigned LaneIndex;
Jim Grosbach5c984e42011-11-15 21:45:55 +00002952 SMLoc S = Parser.getTok().getLoc();
2953 // As an extension (to match gas), support a plain D register or Q register
2954 // (without encosing curly braces) as a single or double entry list,
2955 // respectively.
2956 if (Parser.getTok().is(AsmToken::Identifier)) {
2957 int Reg = tryParseRegister();
2958 if (Reg == -1)
2959 return MatchOperand_NoMatch;
2960 SMLoc E = Parser.getTok().getLoc();
2961 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002962 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002963 if (Res != MatchOperand_Success)
2964 return Res;
2965 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002966 case NoLanes:
2967 E = Parser.getTok().getLoc();
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002968 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002969 break;
2970 case AllLanes:
2971 E = Parser.getTok().getLoc();
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002972 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false,
2973 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002974 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002975 case IndexedLane:
2976 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002977 LaneIndex,
2978 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00002979 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002980 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002981 return MatchOperand_Success;
2982 }
2983 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2984 Reg = getDRegFromQReg(Reg);
Jim Grosbach7636bf62011-12-02 00:35:16 +00002985 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002986 if (Res != MatchOperand_Success)
2987 return Res;
2988 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002989 case NoLanes:
2990 E = Parser.getTok().getLoc();
Jim Grosbach28f08c92012-03-05 19:33:30 +00002991 Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0,
Jim Grosbachc0fc4502012-03-06 22:01:44 +00002992 &ARMMCRegisterClasses[ARM::DPairRegClassID]);
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002993 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002994 break;
2995 case AllLanes:
2996 E = Parser.getTok().getLoc();
Jim Grosbachc0fc4502012-03-06 22:01:44 +00002997 Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0,
2998 &ARMMCRegisterClasses[ARM::DPairRegClassID]);
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002999 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, false,
3000 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003001 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003002 case IndexedLane:
3003 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00003004 LaneIndex,
3005 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00003006 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003007 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00003008 return MatchOperand_Success;
3009 }
3010 Error(S, "vector register expected");
3011 return MatchOperand_ParseFail;
3012 }
3013
3014 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbach862019c2011-10-18 23:02:30 +00003015 return MatchOperand_NoMatch;
3016
Jim Grosbach862019c2011-10-18 23:02:30 +00003017 Parser.Lex(); // Eat '{' token.
3018 SMLoc RegLoc = Parser.getTok().getLoc();
3019
3020 int Reg = tryParseRegister();
3021 if (Reg == -1) {
3022 Error(RegLoc, "register expected");
3023 return MatchOperand_ParseFail;
3024 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003025 unsigned Count = 1;
Jim Grosbach276ed032011-12-15 21:54:55 +00003026 int Spacing = 0;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003027 unsigned FirstReg = Reg;
3028 // The list is of D registers, but we also allow Q regs and just interpret
3029 // them as the two D sub-registers.
3030 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
3031 FirstReg = Reg = getDRegFromQReg(Reg);
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003032 Spacing = 1; // double-spacing requires explicit D registers, otherwise
3033 // it's ambiguous with four-register single spaced.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003034 ++Reg;
3035 ++Count;
3036 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00003037 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003038 return MatchOperand_ParseFail;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003039
Jim Grosbache43862b2011-11-15 23:19:15 +00003040 while (Parser.getTok().is(AsmToken::Comma) ||
3041 Parser.getTok().is(AsmToken::Minus)) {
3042 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003043 if (!Spacing)
3044 Spacing = 1; // Register range implies a single spaced list.
3045 else if (Spacing == 2) {
3046 Error(Parser.getTok().getLoc(),
3047 "sequential registers in double spaced list");
3048 return MatchOperand_ParseFail;
3049 }
Jim Grosbache43862b2011-11-15 23:19:15 +00003050 Parser.Lex(); // Eat the minus.
3051 SMLoc EndLoc = Parser.getTok().getLoc();
3052 int EndReg = tryParseRegister();
3053 if (EndReg == -1) {
3054 Error(EndLoc, "register expected");
3055 return MatchOperand_ParseFail;
3056 }
3057 // Allow Q regs and just interpret them as the two D sub-registers.
3058 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
3059 EndReg = getDRegFromQReg(EndReg) + 1;
3060 // If the register is the same as the start reg, there's nothing
3061 // more to do.
3062 if (Reg == EndReg)
3063 continue;
3064 // The register must be in the same register class as the first.
3065 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
3066 Error(EndLoc, "invalid register in register list");
3067 return MatchOperand_ParseFail;
3068 }
3069 // Ranges must go from low to high.
3070 if (Reg > EndReg) {
3071 Error(EndLoc, "bad range in register list");
3072 return MatchOperand_ParseFail;
3073 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00003074 // Parse the lane specifier if present.
3075 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003076 unsigned NextLaneIndex;
3077 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003078 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003079 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003080 Error(EndLoc, "mismatched lane index in register list");
3081 return MatchOperand_ParseFail;
3082 }
3083 EndLoc = Parser.getTok().getLoc();
Jim Grosbache43862b2011-11-15 23:19:15 +00003084
3085 // Add all the registers in the range to the register list.
3086 Count += EndReg - Reg;
3087 Reg = EndReg;
3088 continue;
3089 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003090 Parser.Lex(); // Eat the comma.
3091 RegLoc = Parser.getTok().getLoc();
3092 int OldReg = Reg;
3093 Reg = tryParseRegister();
3094 if (Reg == -1) {
3095 Error(RegLoc, "register expected");
3096 return MatchOperand_ParseFail;
3097 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003098 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00003099 // It's OK to use the enumeration values directly here rather, as the
3100 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003101 //
3102 // The list is of D registers, but we also allow Q regs and just interpret
3103 // them as the two D sub-registers.
3104 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003105 if (!Spacing)
3106 Spacing = 1; // Register range implies a single spaced list.
3107 else if (Spacing == 2) {
3108 Error(RegLoc,
3109 "invalid register in double-spaced list (must be 'D' register')");
3110 return MatchOperand_ParseFail;
3111 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003112 Reg = getDRegFromQReg(Reg);
3113 if (Reg != OldReg + 1) {
3114 Error(RegLoc, "non-contiguous register range");
3115 return MatchOperand_ParseFail;
3116 }
3117 ++Reg;
3118 Count += 2;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003119 // Parse the lane specifier if present.
3120 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003121 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003122 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003123 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003124 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003125 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003126 Error(EndLoc, "mismatched lane index in register list");
3127 return MatchOperand_ParseFail;
3128 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003129 continue;
3130 }
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003131 // Normal D register.
3132 // Figure out the register spacing (single or double) of the list if
3133 // we don't know it already.
3134 if (!Spacing)
3135 Spacing = 1 + (Reg == OldReg + 2);
3136
3137 // Just check that it's contiguous and keep going.
3138 if (Reg != OldReg + Spacing) {
Jim Grosbach862019c2011-10-18 23:02:30 +00003139 Error(RegLoc, "non-contiguous register range");
3140 return MatchOperand_ParseFail;
3141 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003142 ++Count;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003143 // Parse the lane specifier if present.
3144 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003145 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003146 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003147 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003148 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003149 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003150 Error(EndLoc, "mismatched lane index in register list");
3151 return MatchOperand_ParseFail;
3152 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003153 }
3154
3155 SMLoc E = Parser.getTok().getLoc();
3156 if (Parser.getTok().isNot(AsmToken::RCurly)) {
3157 Error(E, "'}' expected");
3158 return MatchOperand_ParseFail;
3159 }
3160 Parser.Lex(); // Eat '}' token.
3161
Jim Grosbach98b05a52011-11-30 01:09:44 +00003162 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003163 case NoLanes:
Jim Grosbachc0fc4502012-03-06 22:01:44 +00003164 // Two-register operands have been converted to the
Jim Grosbachc3384c92012-03-05 21:43:40 +00003165 // composite register classes.
3166 if (Count == 2) {
3167 const MCRegisterClass *RC = (Spacing == 1) ?
3168 &ARMMCRegisterClasses[ARM::DPairRegClassID] :
3169 &ARMMCRegisterClasses[ARM::DPairSpcRegClassID];
3170 FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC);
3171 }
Jim Grosbach28f08c92012-03-05 19:33:30 +00003172
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003173 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count,
3174 (Spacing == 2), S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003175 break;
3176 case AllLanes:
Jim Grosbachc0fc4502012-03-06 22:01:44 +00003177 // Two-register operands have been converted to the
3178 // composite register classes.
Jim Grosbach4d0983a2012-03-06 23:10:38 +00003179 if (Count == 2) {
3180 const MCRegisterClass *RC = (Spacing == 1) ?
3181 &ARMMCRegisterClasses[ARM::DPairRegClassID] :
3182 &ARMMCRegisterClasses[ARM::DPairSpcRegClassID];
Jim Grosbachc0fc4502012-03-06 22:01:44 +00003183 FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC);
3184 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00003185 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00003186 (Spacing == 2),
Jim Grosbach98b05a52011-11-30 01:09:44 +00003187 S, E));
3188 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003189 case IndexedLane:
3190 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00003191 LaneIndex,
3192 (Spacing == 2),
3193 S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00003194 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003195 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003196 return MatchOperand_Success;
3197}
3198
Jim Grosbach43904292011-07-25 20:14:50 +00003199/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00003200ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003201parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003202 SMLoc S = Parser.getTok().getLoc();
3203 const AsmToken &Tok = Parser.getTok();
3204 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3205 StringRef OptStr = Tok.getString();
3206
3207 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
3208 .Case("sy", ARM_MB::SY)
3209 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003210 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003211 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003212 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003213 .Case("ishst", ARM_MB::ISHST)
3214 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003215 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003216 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003217 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003218 .Case("osh", ARM_MB::OSH)
3219 .Case("oshst", ARM_MB::OSHST)
3220 .Default(~0U);
3221
3222 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00003223 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003224
3225 Parser.Lex(); // Eat identifier token.
3226 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00003227 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003228}
3229
Jim Grosbach43904292011-07-25 20:14:50 +00003230/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003231ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003232parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003233 SMLoc S = Parser.getTok().getLoc();
3234 const AsmToken &Tok = Parser.getTok();
3235 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3236 StringRef IFlagsStr = Tok.getString();
3237
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003238 // An iflags string of "none" is interpreted to mean that none of the AIF
3239 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003240 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003241 if (IFlagsStr != "none") {
3242 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
3243 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
3244 .Case("a", ARM_PROC::A)
3245 .Case("i", ARM_PROC::I)
3246 .Case("f", ARM_PROC::F)
3247 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003248
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003249 // If some specific iflag is already set, it means that some letter is
3250 // present more than once, this is not acceptable.
3251 if (Flag == ~0U || (IFlags & Flag))
3252 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003253
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003254 IFlags |= Flag;
3255 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003256 }
3257
3258 Parser.Lex(); // Eat identifier token.
3259 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
3260 return MatchOperand_Success;
3261}
3262
Jim Grosbach43904292011-07-25 20:14:50 +00003263/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003264ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003265parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003266 SMLoc S = Parser.getTok().getLoc();
3267 const AsmToken &Tok = Parser.getTok();
3268 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3269 StringRef Mask = Tok.getString();
3270
James Molloyacad68d2011-09-28 14:21:38 +00003271 if (isMClass()) {
3272 // See ARMv6-M 10.1.1
Jim Grosbachb84ad4a2012-03-15 21:34:14 +00003273 std::string Name = Mask.lower();
3274 unsigned FlagsVal = StringSwitch<unsigned>(Name)
James Molloyacad68d2011-09-28 14:21:38 +00003275 .Case("apsr", 0)
3276 .Case("iapsr", 1)
3277 .Case("eapsr", 2)
3278 .Case("xpsr", 3)
3279 .Case("ipsr", 5)
3280 .Case("epsr", 6)
3281 .Case("iepsr", 7)
3282 .Case("msp", 8)
3283 .Case("psp", 9)
3284 .Case("primask", 16)
3285 .Case("basepri", 17)
3286 .Case("basepri_max", 18)
3287 .Case("faultmask", 19)
3288 .Case("control", 20)
3289 .Default(~0U);
Jim Grosbach18c8d122011-12-22 17:17:10 +00003290
James Molloyacad68d2011-09-28 14:21:38 +00003291 if (FlagsVal == ~0U)
3292 return MatchOperand_NoMatch;
3293
3294 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
3295 // basepri, basepri_max and faultmask only valid for V7m.
3296 return MatchOperand_NoMatch;
Jim Grosbach18c8d122011-12-22 17:17:10 +00003297
James Molloyacad68d2011-09-28 14:21:38 +00003298 Parser.Lex(); // Eat identifier token.
3299 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3300 return MatchOperand_Success;
3301 }
3302
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003303 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
3304 size_t Start = 0, Next = Mask.find('_');
3305 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00003306 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003307 if (Next != StringRef::npos)
3308 Flags = Mask.slice(Next+1, Mask.size());
3309
3310 // FlagsVal contains the complete mask:
3311 // 3-0: Mask
3312 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3313 unsigned FlagsVal = 0;
3314
3315 if (SpecReg == "apsr") {
3316 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00003317 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003318 .Case("g", 0x4) // same as CPSR_s
3319 .Case("nzcvqg", 0xc) // same as CPSR_fs
3320 .Default(~0U);
3321
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003322 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003323 if (!Flags.empty())
3324 return MatchOperand_NoMatch;
3325 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00003326 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003327 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003328 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00003329 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
3330 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003331 for (int i = 0, e = Flags.size(); i != e; ++i) {
3332 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
3333 .Case("c", 1)
3334 .Case("x", 2)
3335 .Case("s", 4)
3336 .Case("f", 8)
3337 .Default(~0U);
3338
3339 // If some specific flag is already set, it means that some letter is
3340 // present more than once, this is not acceptable.
3341 if (FlagsVal == ~0U || (FlagsVal & Flag))
3342 return MatchOperand_NoMatch;
3343 FlagsVal |= Flag;
3344 }
3345 } else // No match for special register.
3346 return MatchOperand_NoMatch;
3347
Owen Anderson7784f1d2011-10-21 18:43:28 +00003348 // Special register without flags is NOT equivalent to "fc" flags.
3349 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3350 // two lines would enable gas compatibility at the expense of breaking
3351 // round-tripping.
3352 //
3353 // if (!FlagsVal)
3354 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003355
3356 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3357 if (SpecReg == "spsr")
3358 FlagsVal |= 16;
3359
3360 Parser.Lex(); // Eat identifier token.
3361 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3362 return MatchOperand_Success;
3363}
3364
Jim Grosbachf6c05252011-07-21 17:23:04 +00003365ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3366parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3367 int Low, int High) {
3368 const AsmToken &Tok = Parser.getTok();
3369 if (Tok.isNot(AsmToken::Identifier)) {
3370 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3371 return MatchOperand_ParseFail;
3372 }
3373 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00003374 std::string LowerOp = Op.lower();
3375 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00003376 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3377 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3378 return MatchOperand_ParseFail;
3379 }
3380 Parser.Lex(); // Eat shift type token.
3381
3382 // There must be a '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003383 if (Parser.getTok().isNot(AsmToken::Hash) &&
3384 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbachf6c05252011-07-21 17:23:04 +00003385 Error(Parser.getTok().getLoc(), "'#' expected");
3386 return MatchOperand_ParseFail;
3387 }
3388 Parser.Lex(); // Eat hash token.
3389
3390 const MCExpr *ShiftAmount;
3391 SMLoc Loc = Parser.getTok().getLoc();
3392 if (getParser().ParseExpression(ShiftAmount)) {
3393 Error(Loc, "illegal expression");
3394 return MatchOperand_ParseFail;
3395 }
3396 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3397 if (!CE) {
3398 Error(Loc, "constant expression expected");
3399 return MatchOperand_ParseFail;
3400 }
3401 int Val = CE->getValue();
3402 if (Val < Low || Val > High) {
3403 Error(Loc, "immediate value out of range");
3404 return MatchOperand_ParseFail;
3405 }
3406
3407 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3408
3409 return MatchOperand_Success;
3410}
3411
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003412ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3413parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3414 const AsmToken &Tok = Parser.getTok();
3415 SMLoc S = Tok.getLoc();
3416 if (Tok.isNot(AsmToken::Identifier)) {
3417 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3418 return MatchOperand_ParseFail;
3419 }
3420 int Val = StringSwitch<int>(Tok.getString())
3421 .Case("be", 1)
3422 .Case("le", 0)
3423 .Default(-1);
3424 Parser.Lex(); // Eat the token.
3425
3426 if (Val == -1) {
3427 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3428 return MatchOperand_ParseFail;
3429 }
3430 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3431 getContext()),
3432 S, Parser.getTok().getLoc()));
3433 return MatchOperand_Success;
3434}
3435
Jim Grosbach580f4a92011-07-25 22:20:28 +00003436/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3437/// instructions. Legal values are:
3438/// lsl #n 'n' in [0,31]
3439/// asr #n 'n' in [1,32]
3440/// n == 32 encoded as n == 0.
3441ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3442parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3443 const AsmToken &Tok = Parser.getTok();
3444 SMLoc S = Tok.getLoc();
3445 if (Tok.isNot(AsmToken::Identifier)) {
3446 Error(S, "shift operator 'asr' or 'lsl' expected");
3447 return MatchOperand_ParseFail;
3448 }
3449 StringRef ShiftName = Tok.getString();
3450 bool isASR;
3451 if (ShiftName == "lsl" || ShiftName == "LSL")
3452 isASR = false;
3453 else if (ShiftName == "asr" || ShiftName == "ASR")
3454 isASR = true;
3455 else {
3456 Error(S, "shift operator 'asr' or 'lsl' expected");
3457 return MatchOperand_ParseFail;
3458 }
3459 Parser.Lex(); // Eat the operator.
3460
3461 // A '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003462 if (Parser.getTok().isNot(AsmToken::Hash) &&
3463 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach580f4a92011-07-25 22:20:28 +00003464 Error(Parser.getTok().getLoc(), "'#' expected");
3465 return MatchOperand_ParseFail;
3466 }
3467 Parser.Lex(); // Eat hash token.
3468
3469 const MCExpr *ShiftAmount;
3470 SMLoc E = Parser.getTok().getLoc();
3471 if (getParser().ParseExpression(ShiftAmount)) {
3472 Error(E, "malformed shift expression");
3473 return MatchOperand_ParseFail;
3474 }
3475 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3476 if (!CE) {
3477 Error(E, "shift amount must be an immediate");
3478 return MatchOperand_ParseFail;
3479 }
3480
3481 int64_t Val = CE->getValue();
3482 if (isASR) {
3483 // Shift amount must be in [1,32]
3484 if (Val < 1 || Val > 32) {
3485 Error(E, "'asr' shift amount must be in range [1,32]");
3486 return MatchOperand_ParseFail;
3487 }
Owen Anderson0afa0092011-09-26 21:06:22 +00003488 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3489 if (isThumb() && Val == 32) {
3490 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3491 return MatchOperand_ParseFail;
3492 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00003493 if (Val == 32) Val = 0;
3494 } else {
3495 // Shift amount must be in [1,32]
3496 if (Val < 0 || Val > 31) {
3497 Error(E, "'lsr' shift amount must be in range [0,31]");
3498 return MatchOperand_ParseFail;
3499 }
3500 }
3501
3502 E = Parser.getTok().getLoc();
3503 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3504
3505 return MatchOperand_Success;
3506}
3507
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003508/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3509/// of instructions. Legal values are:
3510/// ror #n 'n' in {0, 8, 16, 24}
3511ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3512parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3513 const AsmToken &Tok = Parser.getTok();
3514 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00003515 if (Tok.isNot(AsmToken::Identifier))
3516 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003517 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00003518 if (ShiftName != "ror" && ShiftName != "ROR")
3519 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003520 Parser.Lex(); // Eat the operator.
3521
3522 // A '#' and a rotate amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003523 if (Parser.getTok().isNot(AsmToken::Hash) &&
3524 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003525 Error(Parser.getTok().getLoc(), "'#' expected");
3526 return MatchOperand_ParseFail;
3527 }
3528 Parser.Lex(); // Eat hash token.
3529
3530 const MCExpr *ShiftAmount;
3531 SMLoc E = Parser.getTok().getLoc();
3532 if (getParser().ParseExpression(ShiftAmount)) {
3533 Error(E, "malformed rotate expression");
3534 return MatchOperand_ParseFail;
3535 }
3536 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3537 if (!CE) {
3538 Error(E, "rotate amount must be an immediate");
3539 return MatchOperand_ParseFail;
3540 }
3541
3542 int64_t Val = CE->getValue();
3543 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3544 // normally, zero is represented in asm by omitting the rotate operand
3545 // entirely.
3546 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3547 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3548 return MatchOperand_ParseFail;
3549 }
3550
3551 E = Parser.getTok().getLoc();
3552 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3553
3554 return MatchOperand_Success;
3555}
3556
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003557ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3558parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3559 SMLoc S = Parser.getTok().getLoc();
3560 // The bitfield descriptor is really two operands, the LSB and the width.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003561 if (Parser.getTok().isNot(AsmToken::Hash) &&
3562 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003563 Error(Parser.getTok().getLoc(), "'#' expected");
3564 return MatchOperand_ParseFail;
3565 }
3566 Parser.Lex(); // Eat hash token.
3567
3568 const MCExpr *LSBExpr;
3569 SMLoc E = Parser.getTok().getLoc();
3570 if (getParser().ParseExpression(LSBExpr)) {
3571 Error(E, "malformed immediate expression");
3572 return MatchOperand_ParseFail;
3573 }
3574 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3575 if (!CE) {
3576 Error(E, "'lsb' operand must be an immediate");
3577 return MatchOperand_ParseFail;
3578 }
3579
3580 int64_t LSB = CE->getValue();
3581 // The LSB must be in the range [0,31]
3582 if (LSB < 0 || LSB > 31) {
3583 Error(E, "'lsb' operand must be in the range [0,31]");
3584 return MatchOperand_ParseFail;
3585 }
3586 E = Parser.getTok().getLoc();
3587
3588 // Expect another immediate operand.
3589 if (Parser.getTok().isNot(AsmToken::Comma)) {
3590 Error(Parser.getTok().getLoc(), "too few operands");
3591 return MatchOperand_ParseFail;
3592 }
3593 Parser.Lex(); // Eat hash token.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003594 if (Parser.getTok().isNot(AsmToken::Hash) &&
3595 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003596 Error(Parser.getTok().getLoc(), "'#' expected");
3597 return MatchOperand_ParseFail;
3598 }
3599 Parser.Lex(); // Eat hash token.
3600
3601 const MCExpr *WidthExpr;
3602 if (getParser().ParseExpression(WidthExpr)) {
3603 Error(E, "malformed immediate expression");
3604 return MatchOperand_ParseFail;
3605 }
3606 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3607 if (!CE) {
3608 Error(E, "'width' operand must be an immediate");
3609 return MatchOperand_ParseFail;
3610 }
3611
3612 int64_t Width = CE->getValue();
3613 // The LSB must be in the range [1,32-lsb]
3614 if (Width < 1 || Width > 32 - LSB) {
3615 Error(E, "'width' operand must be in the range [1,32-lsb]");
3616 return MatchOperand_ParseFail;
3617 }
3618 E = Parser.getTok().getLoc();
3619
3620 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3621
3622 return MatchOperand_Success;
3623}
3624
Jim Grosbach7ce05792011-08-03 23:50:40 +00003625ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3626parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3627 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003628 // postidx_reg := '+' register {, shift}
3629 // | '-' register {, shift}
3630 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003631
3632 // This method must return MatchOperand_NoMatch without consuming any tokens
3633 // in the case where there is no match, as other alternatives take other
3634 // parse methods.
3635 AsmToken Tok = Parser.getTok();
3636 SMLoc S = Tok.getLoc();
3637 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003638 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003639 int Reg = -1;
3640 if (Tok.is(AsmToken::Plus)) {
3641 Parser.Lex(); // Eat the '+' token.
3642 haveEaten = true;
3643 } else if (Tok.is(AsmToken::Minus)) {
3644 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003645 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003646 haveEaten = true;
3647 }
3648 if (Parser.getTok().is(AsmToken::Identifier))
3649 Reg = tryParseRegister();
3650 if (Reg == -1) {
3651 if (!haveEaten)
3652 return MatchOperand_NoMatch;
3653 Error(Parser.getTok().getLoc(), "register expected");
3654 return MatchOperand_ParseFail;
3655 }
3656 SMLoc E = Parser.getTok().getLoc();
3657
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003658 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3659 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003660 if (Parser.getTok().is(AsmToken::Comma)) {
3661 Parser.Lex(); // Eat the ','.
3662 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3663 return MatchOperand_ParseFail;
3664 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003665
3666 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3667 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003668
3669 return MatchOperand_Success;
3670}
3671
Jim Grosbach251bf252011-08-10 21:56:18 +00003672ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3673parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3674 // Check for a post-index addressing register operand. Specifically:
3675 // am3offset := '+' register
3676 // | '-' register
3677 // | register
3678 // | # imm
3679 // | # + imm
3680 // | # - imm
3681
3682 // This method must return MatchOperand_NoMatch without consuming any tokens
3683 // in the case where there is no match, as other alternatives take other
3684 // parse methods.
3685 AsmToken Tok = Parser.getTok();
3686 SMLoc S = Tok.getLoc();
3687
3688 // Do immediates first, as we always parse those if we have a '#'.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003689 if (Parser.getTok().is(AsmToken::Hash) ||
3690 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach251bf252011-08-10 21:56:18 +00003691 Parser.Lex(); // Eat the '#'.
3692 // Explicitly look for a '-', as we need to encode negative zero
3693 // differently.
3694 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3695 const MCExpr *Offset;
3696 if (getParser().ParseExpression(Offset))
3697 return MatchOperand_ParseFail;
3698 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3699 if (!CE) {
3700 Error(S, "constant expression expected");
3701 return MatchOperand_ParseFail;
3702 }
3703 SMLoc E = Tok.getLoc();
3704 // Negative zero is encoded as the flag value INT32_MIN.
3705 int32_t Val = CE->getValue();
3706 if (isNegative && Val == 0)
3707 Val = INT32_MIN;
3708
3709 Operands.push_back(
3710 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3711
3712 return MatchOperand_Success;
3713 }
3714
3715
3716 bool haveEaten = false;
3717 bool isAdd = true;
3718 int Reg = -1;
3719 if (Tok.is(AsmToken::Plus)) {
3720 Parser.Lex(); // Eat the '+' token.
3721 haveEaten = true;
3722 } else if (Tok.is(AsmToken::Minus)) {
3723 Parser.Lex(); // Eat the '-' token.
3724 isAdd = false;
3725 haveEaten = true;
3726 }
3727 if (Parser.getTok().is(AsmToken::Identifier))
3728 Reg = tryParseRegister();
3729 if (Reg == -1) {
3730 if (!haveEaten)
3731 return MatchOperand_NoMatch;
3732 Error(Parser.getTok().getLoc(), "register expected");
3733 return MatchOperand_ParseFail;
3734 }
3735 SMLoc E = Parser.getTok().getLoc();
3736
3737 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3738 0, S, E));
3739
3740 return MatchOperand_Success;
3741}
3742
Jim Grosbacha77295d2011-09-08 22:07:06 +00003743/// cvtT2LdrdPre - 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::
3747cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3748 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3749 // Rt, Rt2
3750 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3751 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3752 // Create a writeback register dummy placeholder.
3753 Inst.addOperand(MCOperand::CreateReg(0));
3754 // addr
3755 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3756 // pred
3757 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3758 return true;
3759}
3760
3761/// cvtT2StrdPre - Convert parsed operands to MCInst.
3762/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3763/// when they refer multiple MIOperands inside a single one.
3764bool ARMAsmParser::
3765cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3766 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3767 // Create a writeback register dummy placeholder.
3768 Inst.addOperand(MCOperand::CreateReg(0));
3769 // Rt, Rt2
3770 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3771 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3772 // addr
3773 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3774 // pred
3775 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3776 return true;
3777}
3778
Jim Grosbacheeec0252011-09-08 00:39:19 +00003779/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3780/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3781/// when they refer multiple MIOperands inside a single one.
3782bool ARMAsmParser::
3783cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3784 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3785 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3786
3787 // Create a writeback register dummy placeholder.
3788 Inst.addOperand(MCOperand::CreateImm(0));
3789
3790 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3791 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3792 return true;
3793}
3794
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003795/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3796/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3797/// when they refer multiple MIOperands inside a single one.
3798bool ARMAsmParser::
3799cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3800 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3801 // Create a writeback register dummy placeholder.
3802 Inst.addOperand(MCOperand::CreateImm(0));
3803 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3804 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3805 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3806 return true;
3807}
3808
Jim Grosbach1355cf12011-07-26 17:10:22 +00003809/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003810/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3811/// when they refer multiple MIOperands inside a single one.
3812bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003813cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003814 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3815 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3816
3817 // Create a writeback register dummy placeholder.
3818 Inst.addOperand(MCOperand::CreateImm(0));
3819
Jim Grosbach7ce05792011-08-03 23:50:40 +00003820 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003821 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3822 return true;
3823}
3824
Owen Anderson9ab0f252011-08-26 20:43:14 +00003825/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3826/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3827/// when they refer multiple MIOperands inside a single one.
3828bool ARMAsmParser::
3829cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3830 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3831 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3832
3833 // Create a writeback register dummy placeholder.
3834 Inst.addOperand(MCOperand::CreateImm(0));
3835
3836 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3837 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3838 return true;
3839}
3840
3841
Jim Grosbach548340c2011-08-11 19:22:40 +00003842/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3843/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3844/// when they refer multiple MIOperands inside a single one.
3845bool ARMAsmParser::
3846cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3847 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3848 // Create a writeback register dummy placeholder.
3849 Inst.addOperand(MCOperand::CreateImm(0));
3850 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3851 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3852 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3853 return true;
3854}
3855
Jim Grosbach1355cf12011-07-26 17:10:22 +00003856/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003857/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3858/// when they refer multiple MIOperands inside a single one.
3859bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003860cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003861 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3862 // Create a writeback register dummy placeholder.
3863 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003864 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3865 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3866 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003867 return true;
3868}
3869
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003870/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3871/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3872/// when they refer multiple MIOperands inside a single one.
3873bool ARMAsmParser::
3874cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3875 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3876 // Create a writeback register dummy placeholder.
3877 Inst.addOperand(MCOperand::CreateImm(0));
3878 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3879 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3880 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3881 return true;
3882}
3883
Jim Grosbach7ce05792011-08-03 23:50:40 +00003884/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3885/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3886/// when they refer multiple MIOperands inside a single one.
3887bool ARMAsmParser::
3888cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3889 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3890 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003891 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003892 // Create a writeback register dummy placeholder.
3893 Inst.addOperand(MCOperand::CreateImm(0));
3894 // addr
3895 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3896 // offset
3897 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3898 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003899 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3900 return true;
3901}
3902
Jim Grosbach7ce05792011-08-03 23:50:40 +00003903/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003904/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3905/// when they refer multiple MIOperands inside a single one.
3906bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003907cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3908 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3909 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003910 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003911 // Create a writeback register dummy placeholder.
3912 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003913 // addr
3914 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3915 // offset
3916 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3917 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003918 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3919 return true;
3920}
3921
Jim Grosbach7ce05792011-08-03 23:50:40 +00003922/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003923/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3924/// when they refer multiple MIOperands inside a single one.
3925bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003926cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3927 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003928 // Create a writeback register dummy placeholder.
3929 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003930 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003931 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003932 // addr
3933 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3934 // offset
3935 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3936 // pred
3937 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3938 return true;
3939}
3940
3941/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3942/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3943/// when they refer multiple MIOperands inside a single one.
3944bool ARMAsmParser::
3945cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3946 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3947 // Create a writeback register dummy placeholder.
3948 Inst.addOperand(MCOperand::CreateImm(0));
3949 // Rt
3950 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3951 // addr
3952 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3953 // offset
3954 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3955 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003956 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3957 return true;
3958}
3959
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003960/// cvtLdrdPre - Convert parsed operands to MCInst.
3961/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3962/// when they refer multiple MIOperands inside a single one.
3963bool ARMAsmParser::
3964cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3965 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3966 // Rt, Rt2
3967 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3968 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3969 // Create a writeback register dummy placeholder.
3970 Inst.addOperand(MCOperand::CreateImm(0));
3971 // addr
3972 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3973 // pred
3974 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3975 return true;
3976}
3977
Jim Grosbach14605d12011-08-11 20:28:23 +00003978/// cvtStrdPre - Convert parsed operands to MCInst.
3979/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3980/// when they refer multiple MIOperands inside a single one.
3981bool ARMAsmParser::
3982cvtStrdPre(MCInst &Inst, unsigned Opcode,
3983 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3984 // Create a writeback register dummy placeholder.
3985 Inst.addOperand(MCOperand::CreateImm(0));
3986 // Rt, Rt2
3987 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3988 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3989 // addr
3990 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3991 // pred
3992 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3993 return true;
3994}
3995
Jim Grosbach623a4542011-08-10 22:42:16 +00003996/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3997/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3998/// when they refer multiple MIOperands inside a single one.
3999bool ARMAsmParser::
4000cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
4001 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4002 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
4003 // Create a writeback register dummy placeholder.
4004 Inst.addOperand(MCOperand::CreateImm(0));
4005 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
4006 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4007 return true;
4008}
4009
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004010/// cvtThumbMultiple- Convert parsed operands to MCInst.
4011/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4012/// when they refer multiple MIOperands inside a single one.
4013bool ARMAsmParser::
4014cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
4015 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4016 // The second source operand must be the same register as the destination
4017 // operand.
4018 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00004019 (((ARMOperand*)Operands[3])->getReg() !=
4020 ((ARMOperand*)Operands[5])->getReg()) &&
4021 (((ARMOperand*)Operands[3])->getReg() !=
4022 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004023 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00004024 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004025 return false;
4026 }
4027 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
4028 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach1b332862011-11-10 22:10:12 +00004029 // If we have a three-operand form, make sure to set Rn to be the operand
4030 // that isn't the same as Rd.
4031 unsigned RegOp = 4;
4032 if (Operands.size() == 6 &&
4033 ((ARMOperand*)Operands[4])->getReg() ==
4034 ((ARMOperand*)Operands[3])->getReg())
4035 RegOp = 5;
4036 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
4037 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004038 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
4039
4040 return true;
4041}
Jim Grosbach623a4542011-08-10 22:42:16 +00004042
Jim Grosbach12431322011-10-24 22:16:58 +00004043bool ARMAsmParser::
4044cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
4045 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4046 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004047 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00004048 // Create a writeback register dummy placeholder.
4049 Inst.addOperand(MCOperand::CreateImm(0));
4050 // Vn
4051 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4052 // pred
4053 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4054 return true;
4055}
4056
4057bool ARMAsmParser::
4058cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
4059 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4060 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004061 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00004062 // Create a writeback register dummy placeholder.
4063 Inst.addOperand(MCOperand::CreateImm(0));
4064 // Vn
4065 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4066 // Vm
4067 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4068 // pred
4069 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4070 return true;
4071}
4072
Jim Grosbach4334e032011-10-31 21:50:31 +00004073bool ARMAsmParser::
4074cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
4075 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4076 // Create a writeback register dummy placeholder.
4077 Inst.addOperand(MCOperand::CreateImm(0));
4078 // Vn
4079 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4080 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004081 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00004082 // pred
4083 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4084 return true;
4085}
4086
4087bool ARMAsmParser::
4088cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
4089 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4090 // Create a writeback register dummy placeholder.
4091 Inst.addOperand(MCOperand::CreateImm(0));
4092 // Vn
4093 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4094 // Vm
4095 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4096 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004097 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00004098 // pred
4099 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4100 return true;
4101}
4102
Bill Wendlinge7176102010-11-06 22:36:58 +00004103/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004104/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00004105bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00004106parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00004107 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00004108 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00004109 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00004110 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004111 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004112
Sean Callanan18b83232010-01-19 21:44:56 +00004113 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00004114 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00004115 if (BaseRegNum == -1)
4116 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004117
Daniel Dunbar05710932011-01-18 05:34:17 +00004118 // The next token must either be a comma or a closing bracket.
4119 const AsmToken &Tok = Parser.getTok();
4120 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004121 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00004122
Jim Grosbach7ce05792011-08-03 23:50:40 +00004123 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00004124 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004125 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004126
Jim Grosbach7ce05792011-08-03 23:50:40 +00004127 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004128 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00004129
Jim Grosbachfb12f352011-09-19 18:42:21 +00004130 // If there's a pre-indexing writeback marker, '!', just add it as a token
4131 // operand. It's rather odd, but syntactically valid.
4132 if (Parser.getTok().is(AsmToken::Exclaim)) {
4133 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4134 Parser.Lex(); // Eat the '!'.
4135 }
4136
Jim Grosbach7ce05792011-08-03 23:50:40 +00004137 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004138 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004139
Jim Grosbach7ce05792011-08-03 23:50:40 +00004140 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
4141 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004142
Jim Grosbach57dcb852011-10-11 17:29:55 +00004143 // If we have a ':', it's an alignment specifier.
4144 if (Parser.getTok().is(AsmToken::Colon)) {
4145 Parser.Lex(); // Eat the ':'.
4146 E = Parser.getTok().getLoc();
4147
4148 const MCExpr *Expr;
4149 if (getParser().ParseExpression(Expr))
4150 return true;
4151
4152 // The expression has to be a constant. Memory references with relocations
4153 // don't come through here, as they use the <label> forms of the relevant
4154 // instructions.
4155 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4156 if (!CE)
4157 return Error (E, "constant expression expected");
4158
4159 unsigned Align = 0;
4160 switch (CE->getValue()) {
4161 default:
Jim Grosbacheeaf1c12011-12-19 18:31:43 +00004162 return Error(E,
4163 "alignment specifier must be 16, 32, 64, 128, or 256 bits");
4164 case 16: Align = 2; break;
4165 case 32: Align = 4; break;
Jim Grosbach57dcb852011-10-11 17:29:55 +00004166 case 64: Align = 8; break;
4167 case 128: Align = 16; break;
4168 case 256: Align = 32; break;
4169 }
4170
4171 // Now we should have the closing ']'
4172 E = Parser.getTok().getLoc();
4173 if (Parser.getTok().isNot(AsmToken::RBrac))
4174 return Error(E, "']' expected");
4175 Parser.Lex(); // Eat right bracket token.
4176
4177 // Don't worry about range checking the value here. That's handled by
4178 // the is*() predicates.
4179 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
4180 ARM_AM::no_shift, 0, Align,
4181 false, S, E));
4182
4183 // If there's a pre-indexing writeback marker, '!', just add it as a token
4184 // operand.
4185 if (Parser.getTok().is(AsmToken::Exclaim)) {
4186 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4187 Parser.Lex(); // Eat the '!'.
4188 }
4189
4190 return false;
4191 }
4192
4193 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004194 // offset. Be friendly and also accept a plain integer (without a leading
4195 // hash) for gas compatibility.
4196 if (Parser.getTok().is(AsmToken::Hash) ||
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004197 Parser.getTok().is(AsmToken::Dollar) ||
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004198 Parser.getTok().is(AsmToken::Integer)) {
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004199 if (Parser.getTok().isNot(AsmToken::Integer))
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004200 Parser.Lex(); // Eat the '#'.
Jim Grosbach7ce05792011-08-03 23:50:40 +00004201 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004202
Owen Anderson0da10cf2011-08-29 19:36:44 +00004203 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00004204 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004205 if (getParser().ParseExpression(Offset))
4206 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004207
4208 // The expression has to be a constant. Memory references with relocations
4209 // don't come through here, as they use the <label> forms of the relevant
4210 // instructions.
4211 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
4212 if (!CE)
4213 return Error (E, "constant expression expected");
4214
Owen Anderson0da10cf2011-08-29 19:36:44 +00004215 // If the constant was #-0, represent it as INT32_MIN.
4216 int32_t Val = CE->getValue();
4217 if (isNegative && Val == 0)
4218 CE = MCConstantExpr::Create(INT32_MIN, getContext());
4219
Jim Grosbach7ce05792011-08-03 23:50:40 +00004220 // Now we should have the closing ']'
4221 E = Parser.getTok().getLoc();
4222 if (Parser.getTok().isNot(AsmToken::RBrac))
4223 return Error(E, "']' expected");
4224 Parser.Lex(); // Eat right bracket token.
4225
4226 // Don't worry about range checking the value here. That's handled by
4227 // the is*() predicates.
4228 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004229 ARM_AM::no_shift, 0, 0,
4230 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00004231
4232 // If there's a pre-indexing writeback marker, '!', just add it as a token
4233 // operand.
4234 if (Parser.getTok().is(AsmToken::Exclaim)) {
4235 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4236 Parser.Lex(); // Eat the '!'.
4237 }
4238
4239 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004240 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004241
4242 // The register offset is optionally preceded by a '+' or '-'
4243 bool isNegative = false;
4244 if (Parser.getTok().is(AsmToken::Minus)) {
4245 isNegative = true;
4246 Parser.Lex(); // Eat the '-'.
4247 } else if (Parser.getTok().is(AsmToken::Plus)) {
4248 // Nothing to do.
4249 Parser.Lex(); // Eat the '+'.
4250 }
4251
4252 E = Parser.getTok().getLoc();
4253 int OffsetRegNum = tryParseRegister();
4254 if (OffsetRegNum == -1)
4255 return Error(E, "register expected");
4256
4257 // If there's a shift operator, handle it.
4258 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004259 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004260 if (Parser.getTok().is(AsmToken::Comma)) {
4261 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004262 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004263 return true;
4264 }
4265
4266 // Now we should have the closing ']'
4267 E = Parser.getTok().getLoc();
4268 if (Parser.getTok().isNot(AsmToken::RBrac))
4269 return Error(E, "']' expected");
4270 Parser.Lex(); // Eat right bracket token.
4271
4272 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004273 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00004274 S, E));
4275
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00004276 // If there's a pre-indexing writeback marker, '!', just add it as a token
4277 // operand.
4278 if (Parser.getTok().is(AsmToken::Exclaim)) {
4279 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4280 Parser.Lex(); // Eat the '!'.
4281 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004282
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004283 return false;
4284}
4285
Jim Grosbach7ce05792011-08-03 23:50:40 +00004286/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004287/// ( lsl | lsr | asr | ror ) , # shift_amount
4288/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00004289/// return true if it parses a shift otherwise it returns false.
4290bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
4291 unsigned &Amount) {
4292 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00004293 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004294 if (Tok.isNot(AsmToken::Identifier))
4295 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00004296 StringRef ShiftName = Tok.getString();
Jim Grosbachaf4edea2011-12-07 23:40:58 +00004297 if (ShiftName == "lsl" || ShiftName == "LSL" ||
4298 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson00828302011-03-18 22:50:18 +00004299 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004300 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00004301 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004302 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00004303 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004304 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00004305 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004306 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00004307 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004308 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00004309 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00004310 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004311
Jim Grosbach7ce05792011-08-03 23:50:40 +00004312 // rrx stands alone.
4313 Amount = 0;
4314 if (St != ARM_AM::rrx) {
4315 Loc = Parser.getTok().getLoc();
4316 // A '#' and a shift amount.
4317 const AsmToken &HashTok = Parser.getTok();
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004318 if (HashTok.isNot(AsmToken::Hash) &&
4319 HashTok.isNot(AsmToken::Dollar))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004320 return Error(HashTok.getLoc(), "'#' expected");
4321 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004322
Jim Grosbach7ce05792011-08-03 23:50:40 +00004323 const MCExpr *Expr;
4324 if (getParser().ParseExpression(Expr))
4325 return true;
4326 // Range check the immediate.
4327 // lsl, ror: 0 <= imm <= 31
4328 // lsr, asr: 0 <= imm <= 32
4329 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4330 if (!CE)
4331 return Error(Loc, "shift amount must be an immediate");
4332 int64_t Imm = CE->getValue();
4333 if (Imm < 0 ||
4334 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4335 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4336 return Error(Loc, "immediate shift value out of range");
4337 Amount = Imm;
4338 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004339
4340 return false;
4341}
4342
Jim Grosbach9d390362011-10-03 23:38:36 +00004343/// parseFPImm - A floating point immediate expression operand.
4344ARMAsmParser::OperandMatchResultTy ARMAsmParser::
4345parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach51222d12012-01-20 18:09:51 +00004346 // Anything that can accept a floating point constant as an operand
4347 // needs to go through here, as the regular ParseExpression is
4348 // integer only.
4349 //
4350 // This routine still creates a generic Immediate operand, containing
4351 // a bitcast of the 64-bit floating point value. The various operands
4352 // that accept floats can check whether the value is valid for them
4353 // via the standard is*() predicates.
4354
Jim Grosbach9d390362011-10-03 23:38:36 +00004355 SMLoc S = Parser.getTok().getLoc();
4356
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004357 if (Parser.getTok().isNot(AsmToken::Hash) &&
4358 Parser.getTok().isNot(AsmToken::Dollar))
Jim Grosbach9d390362011-10-03 23:38:36 +00004359 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00004360
4361 // Disambiguate the VMOV forms that can accept an FP immediate.
4362 // vmov.f32 <sreg>, #imm
4363 // vmov.f64 <dreg>, #imm
4364 // vmov.f32 <dreg>, #imm @ vector f32x2
4365 // vmov.f32 <qreg>, #imm @ vector f32x4
4366 //
4367 // There are also the NEON VMOV instructions which expect an
4368 // integer constant. Make sure we don't try to parse an FPImm
4369 // for these:
4370 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4371 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4372 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4373 TyOp->getToken() != ".f64"))
4374 return MatchOperand_NoMatch;
4375
Jim Grosbach9d390362011-10-03 23:38:36 +00004376 Parser.Lex(); // Eat the '#'.
4377
4378 // Handle negation, as that still comes through as a separate token.
4379 bool isNegative = false;
4380 if (Parser.getTok().is(AsmToken::Minus)) {
4381 isNegative = true;
4382 Parser.Lex();
4383 }
4384 const AsmToken &Tok = Parser.getTok();
Jim Grosbachae69f702012-01-19 02:47:30 +00004385 SMLoc Loc = Tok.getLoc();
Jim Grosbach9d390362011-10-03 23:38:36 +00004386 if (Tok.is(AsmToken::Real)) {
Jim Grosbach51222d12012-01-20 18:09:51 +00004387 APFloat RealVal(APFloat::IEEEsingle, Tok.getString());
Jim Grosbach9d390362011-10-03 23:38:36 +00004388 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4389 // If we had a '-' in front, toggle the sign bit.
Jim Grosbach51222d12012-01-20 18:09:51 +00004390 IntVal ^= (uint64_t)isNegative << 31;
Jim Grosbach9d390362011-10-03 23:38:36 +00004391 Parser.Lex(); // Eat the token.
Jim Grosbach51222d12012-01-20 18:09:51 +00004392 Operands.push_back(ARMOperand::CreateImm(
4393 MCConstantExpr::Create(IntVal, getContext()),
4394 S, Parser.getTok().getLoc()));
Jim Grosbach9d390362011-10-03 23:38:36 +00004395 return MatchOperand_Success;
4396 }
Jim Grosbach51222d12012-01-20 18:09:51 +00004397 // Also handle plain integers. Instructions which allow floating point
4398 // immediates also allow a raw encoded 8-bit value.
Jim Grosbach9d390362011-10-03 23:38:36 +00004399 if (Tok.is(AsmToken::Integer)) {
4400 int64_t Val = Tok.getIntVal();
4401 Parser.Lex(); // Eat the token.
4402 if (Val > 255 || Val < 0) {
Jim Grosbachae69f702012-01-19 02:47:30 +00004403 Error(Loc, "encoded floating point value out of range");
Jim Grosbach9d390362011-10-03 23:38:36 +00004404 return MatchOperand_ParseFail;
4405 }
Jim Grosbach51222d12012-01-20 18:09:51 +00004406 double RealVal = ARM_AM::getFPImmFloat(Val);
4407 Val = APFloat(APFloat::IEEEdouble, RealVal).bitcastToAPInt().getZExtValue();
4408 Operands.push_back(ARMOperand::CreateImm(
4409 MCConstantExpr::Create(Val, getContext()), S,
4410 Parser.getTok().getLoc()));
Jim Grosbach9d390362011-10-03 23:38:36 +00004411 return MatchOperand_Success;
4412 }
4413
Jim Grosbachae69f702012-01-19 02:47:30 +00004414 Error(Loc, "invalid floating point immediate");
Jim Grosbach9d390362011-10-03 23:38:36 +00004415 return MatchOperand_ParseFail;
4416}
Jim Grosbach51222d12012-01-20 18:09:51 +00004417
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004418/// Parse a arm instruction operand. For now this parses the operand regardless
4419/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004420bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004421 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00004422 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004423
4424 // Check if the current operand has a custom associated parser, if so, try to
4425 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00004426 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4427 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004428 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00004429 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4430 // there was a match, but an error occurred, in which case, just return that
4431 // the operand parsing failed.
4432 if (ResTy == MatchOperand_ParseFail)
4433 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004434
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004435 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00004436 default:
4437 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00004438 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00004439 case AsmToken::Identifier: {
Jim Grosbach1355cf12011-07-26 17:10:22 +00004440 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00004441 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00004442 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00004443 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00004444 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00004445 else if (Res == -1) // irrecoverable error
4446 return true;
Jim Grosbach3cbe43f2011-12-20 22:26:38 +00004447 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbachb84ad4a2012-03-15 21:34:14 +00004448 if (Mnemonic == "vmrs" &&
4449 Parser.getTok().getString().equals_lower("apsr_nzcv")) {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004450 S = Parser.getTok().getLoc();
4451 Parser.Lex();
Jim Grosbachb84ad4a2012-03-15 21:34:14 +00004452 Operands.push_back(ARMOperand::CreateToken("APSR_nzcv", S));
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004453 return false;
4454 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00004455
4456 // Fall though for the Identifier case that is not a register or a
4457 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00004458 }
Jim Grosbach758a5192011-10-26 21:14:08 +00004459 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00004460 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00004461 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00004462 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00004463 // This was not a register so parse other operands that start with an
4464 // identifier (like labels) as expressions and create them as immediates.
4465 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00004466 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00004467 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004468 return true;
Sean Callanan76264762010-04-02 22:27:05 +00004469 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004470 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4471 return false;
4472 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004473 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004474 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00004475 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004476 return parseRegisterList(Operands);
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004477 case AsmToken::Dollar:
Owen Anderson63553c72011-08-29 17:17:09 +00004478 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00004479 // #42 -> immediate.
4480 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00004481 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004482 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00004483 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00004484 const MCExpr *ImmVal;
4485 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004486 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00004487 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbached6a0c52011-11-01 22:37:37 +00004488 if (CE) {
4489 int32_t Val = CE->getValue();
4490 if (isNegative && Val == 0)
4491 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Anderson63553c72011-08-29 17:17:09 +00004492 }
Sean Callanan76264762010-04-02 22:27:05 +00004493 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004494 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4495 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00004496 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004497 case AsmToken::Colon: {
4498 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00004499 // FIXME: Check it's an expression prefix,
4500 // e.g. (FOO - :lower16:BAR) isn't legal.
4501 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004502 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004503 return true;
4504
Evan Cheng75972122011-01-13 07:58:56 +00004505 const MCExpr *SubExprVal;
4506 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004507 return true;
4508
Evan Cheng75972122011-01-13 07:58:56 +00004509 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4510 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00004511 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00004512 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00004513 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004514 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004515 }
4516}
4517
Jim Grosbach1355cf12011-07-26 17:10:22 +00004518// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00004519// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004520bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00004521 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004522
4523 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00004524 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00004525 Parser.Lex(); // Eat ':'
4526
4527 if (getLexer().isNot(AsmToken::Identifier)) {
4528 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4529 return true;
4530 }
4531
4532 StringRef IDVal = Parser.getTok().getIdentifier();
4533 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00004534 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004535 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00004536 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004537 } else {
4538 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4539 return true;
4540 }
4541 Parser.Lex();
4542
4543 if (getLexer().isNot(AsmToken::Colon)) {
4544 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4545 return true;
4546 }
4547 Parser.Lex(); // Eat the last ':'
4548 return false;
4549}
4550
Daniel Dunbar352e1482011-01-11 15:59:50 +00004551/// \brief Given a mnemonic, split out possible predication code and carry
4552/// setting letters to form a canonical mnemonic and flags.
4553//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004554// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00004555// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004556StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00004557 unsigned &PredicationCode,
4558 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004559 unsigned &ProcessorIMod,
4560 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004561 PredicationCode = ARMCC::AL;
4562 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004563 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004564
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004565 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00004566 //
4567 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00004568 if ((Mnemonic == "movs" && isThumb()) ||
4569 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4570 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4571 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4572 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4573 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4574 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
Jim Grosbach68490192011-12-19 19:43:50 +00004575 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" ||
4576 Mnemonic == "fmuls")
Daniel Dunbar352e1482011-01-11 15:59:50 +00004577 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00004578
Jim Grosbach3f00e312011-07-11 17:09:57 +00004579 // First, split out any predication code. Ignore mnemonics we know aren't
4580 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00004581 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00004582 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00004583 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00004584 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00004585 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4586 .Case("eq", ARMCC::EQ)
4587 .Case("ne", ARMCC::NE)
4588 .Case("hs", ARMCC::HS)
4589 .Case("cs", ARMCC::HS)
4590 .Case("lo", ARMCC::LO)
4591 .Case("cc", ARMCC::LO)
4592 .Case("mi", ARMCC::MI)
4593 .Case("pl", ARMCC::PL)
4594 .Case("vs", ARMCC::VS)
4595 .Case("vc", ARMCC::VC)
4596 .Case("hi", ARMCC::HI)
4597 .Case("ls", ARMCC::LS)
4598 .Case("ge", ARMCC::GE)
4599 .Case("lt", ARMCC::LT)
4600 .Case("gt", ARMCC::GT)
4601 .Case("le", ARMCC::LE)
4602 .Case("al", ARMCC::AL)
4603 .Default(~0U);
4604 if (CC != ~0U) {
4605 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4606 PredicationCode = CC;
4607 }
Bill Wendling52925b62010-10-29 23:50:21 +00004608 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004609
Daniel Dunbar352e1482011-01-11 15:59:50 +00004610 // Next, determine if we have a carry setting bit. We explicitly ignore all
4611 // the instructions we know end in 's'.
4612 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00004613 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00004614 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4615 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4616 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach67ca1ad2011-12-08 00:49:29 +00004617 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach48171e72011-12-10 00:01:02 +00004618 Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
Jim Grosbach9c397892011-12-19 19:02:41 +00004619 Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" ||
Jim Grosbach6357cae2012-03-15 20:48:18 +00004620 Mnemonic == "fmuls" || Mnemonic == "fcmps" || Mnemonic == "fcmpzs" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00004621 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004622 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4623 CarrySetting = true;
4624 }
4625
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004626 // The "cps" instruction can have a interrupt mode operand which is glued into
4627 // the mnemonic. Check if this is the case, split it and parse the imod op
4628 if (Mnemonic.startswith("cps")) {
4629 // Split out any imod code.
4630 unsigned IMod =
4631 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4632 .Case("ie", ARM_PROC::IE)
4633 .Case("id", ARM_PROC::ID)
4634 .Default(~0U);
4635 if (IMod != ~0U) {
4636 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4637 ProcessorIMod = IMod;
4638 }
4639 }
4640
Jim Grosbach89df9962011-08-26 21:43:41 +00004641 // The "it" instruction has the condition mask on the end of the mnemonic.
4642 if (Mnemonic.startswith("it")) {
4643 ITMask = Mnemonic.slice(2, Mnemonic.size());
4644 Mnemonic = Mnemonic.slice(0, 2);
4645 }
4646
Daniel Dunbar352e1482011-01-11 15:59:50 +00004647 return Mnemonic;
4648}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004649
4650/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4651/// inclusion of carry set or predication code operands.
4652//
4653// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004654void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00004655getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004656 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004657 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4658 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004659 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004660 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004661 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004662 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004663 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004664 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004665 Mnemonic == "mla" || Mnemonic == "smlal" ||
4666 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004667 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004668 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004669 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004670
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004671 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4672 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4673 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4674 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004675 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4676 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004677 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004678 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4679 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4680 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004681 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4682 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004683 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004684 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004685 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004686 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004687
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004688 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004689 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004690 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004691 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004692 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004693}
4694
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004695bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4696 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004697 // FIXME: This is all horribly hacky. We really need a better way to deal
4698 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004699
4700 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4701 // another does not. Specifically, the MOVW instruction does not. So we
4702 // special case it here and remove the defaulted (non-setting) cc_out
4703 // operand if that's the instruction we're trying to match.
4704 //
4705 // We do this as post-processing of the explicit operands rather than just
4706 // conditionally adding the cc_out in the first place because we need
4707 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004708 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004709 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4710 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4711 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4712 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004713
4714 // Register-register 'add' for thumb does not have a cc_out operand
4715 // when there are only two register operands.
4716 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4717 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4718 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4719 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4720 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004721 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004722 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4723 // have to check the immediate range here since Thumb2 has a variant
4724 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004725 if (((isThumb() && Mnemonic == "add") ||
4726 (isThumbTwo() && Mnemonic == "sub")) &&
4727 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004728 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4729 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4730 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004731 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4732 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4733 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004734 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004735 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4736 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004737 // selecting via the generic "add" mnemonic, so to know that we
4738 // should remove the cc_out operand, we have to explicitly check that
4739 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004740 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4741 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004742 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4743 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4744 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4745 // Nest conditions rather than one big 'if' statement for readability.
4746 //
4747 // If either register is a high reg, it's either one of the SP
4748 // variants (handled above) or a 32-bit encoding, so we just
Jim Grosbach12a88632012-01-21 00:07:56 +00004749 // check against T3. If the second register is the PC, this is an
4750 // alternate form of ADR, which uses encoding T4, so check for that too.
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004751 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4752 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
Jim Grosbach12a88632012-01-21 00:07:56 +00004753 static_cast<ARMOperand*>(Operands[4])->getReg() != ARM::PC &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004754 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4755 return false;
4756 // If both registers are low, we're in an IT block, and the immediate is
4757 // in range, we should use encoding T1 instead, which has a cc_out.
4758 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004759 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004760 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4761 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4762 return false;
4763
4764 // Otherwise, we use encoding T4, which does not have a cc_out
4765 // operand.
4766 return true;
4767 }
4768
Jim Grosbach64944f42011-09-14 21:00:40 +00004769 // The thumb2 multiply instruction doesn't have a CCOut register, so
4770 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4771 // use the 16-bit encoding or not.
4772 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4773 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4774 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4775 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4776 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4777 // If the registers aren't low regs, the destination reg isn't the
4778 // same as one of the source regs, or the cc_out operand is zero
4779 // outside of an IT block, we have to use the 32-bit encoding, so
4780 // remove the cc_out operand.
4781 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4782 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach1de0bd12011-11-15 19:29:45 +00004783 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach64944f42011-09-14 21:00:40 +00004784 !inITBlock() ||
4785 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4786 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4787 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4788 static_cast<ARMOperand*>(Operands[4])->getReg())))
4789 return true;
4790
Jim Grosbach7f1ec952011-11-15 19:55:16 +00004791 // Also check the 'mul' syntax variant that doesn't specify an explicit
4792 // destination register.
4793 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4794 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4795 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4796 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4797 // If the registers aren't low regs or the cc_out operand is zero
4798 // outside of an IT block, we have to use the 32-bit encoding, so
4799 // remove the cc_out operand.
4800 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4801 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4802 !inITBlock()))
4803 return true;
4804
Jim Grosbach64944f42011-09-14 21:00:40 +00004805
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004806
Jim Grosbachf69c8042011-08-24 21:42:27 +00004807 // Register-register 'add/sub' for thumb does not have a cc_out operand
4808 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4809 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4810 // right, this will result in better diagnostics (which operand is off)
4811 // anyway.
4812 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4813 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004814 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4815 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4816 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4817 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004818
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004819 return false;
4820}
4821
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004822static bool isDataTypeToken(StringRef Tok) {
4823 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4824 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4825 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4826 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4827 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4828 Tok == ".f" || Tok == ".d";
4829}
4830
4831// FIXME: This bit should probably be handled via an explicit match class
4832// in the .td files that matches the suffix instead of having it be
4833// a literal string token the way it is now.
4834static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4835 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4836}
4837
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004838static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004839/// Parse an arm instruction mnemonic followed by its operands.
4840bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4841 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004842 // Apply mnemonic aliases before doing anything else, as the destination
4843 // mnemnonic may include suffices and we want to handle them normally.
4844 // The generic tblgen'erated code does this later, at the start of
4845 // MatchInstructionImpl(), but that's too late for aliases that include
4846 // any sort of suffix.
4847 unsigned AvailableFeatures = getAvailableFeatures();
4848 applyMnemonicAliases(Name, AvailableFeatures);
4849
Jim Grosbacha39cda72011-12-14 02:16:11 +00004850 // First check for the ARM-specific .req directive.
4851 if (Parser.getTok().is(AsmToken::Identifier) &&
4852 Parser.getTok().getIdentifier() == ".req") {
4853 parseDirectiveReq(Name, NameLoc);
4854 // We always return 'error' for this, as we're done with this
4855 // statement and don't need to match the 'instruction."
4856 return true;
4857 }
4858
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004859 // Create the leading tokens for the mnemonic, split by '.' characters.
4860 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004861 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004862
Daniel Dunbar352e1482011-01-11 15:59:50 +00004863 // Split out the predication code and carry setting flag from the mnemonic.
4864 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004865 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004866 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004867 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004868 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004869 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004870
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004871 // In Thumb1, only the branch (B) instruction can be predicated.
4872 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4873 Parser.EatToEndOfStatement();
4874 return Error(NameLoc, "conditional execution not supported in Thumb1");
4875 }
4876
Jim Grosbachffa32252011-07-19 19:13:28 +00004877 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4878
Jim Grosbach89df9962011-08-26 21:43:41 +00004879 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4880 // is the mask as it will be for the IT encoding if the conditional
4881 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4882 // where the conditional bit0 is zero, the instruction post-processing
4883 // will adjust the mask accordingly.
4884 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004885 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4886 if (ITMask.size() > 3) {
4887 Parser.EatToEndOfStatement();
4888 return Error(Loc, "too many conditions on IT instruction");
4889 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004890 unsigned Mask = 8;
4891 for (unsigned i = ITMask.size(); i != 0; --i) {
4892 char pos = ITMask[i - 1];
4893 if (pos != 't' && pos != 'e') {
4894 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004895 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004896 }
4897 Mask >>= 1;
4898 if (ITMask[i - 1] == 't')
4899 Mask |= 8;
4900 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004901 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004902 }
4903
Jim Grosbachffa32252011-07-19 19:13:28 +00004904 // FIXME: This is all a pretty gross hack. We should automatically handle
4905 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004906
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004907 // Next, add the CCOut and ConditionCode operands, if needed.
4908 //
4909 // For mnemonics which can ever incorporate a carry setting bit or predication
4910 // code, our matching model involves us always generating CCOut and
4911 // ConditionCode operands to match the mnemonic "as written" and then we let
4912 // the matcher deal with finding the right instruction or generating an
4913 // appropriate error.
4914 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004915 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004916
Jim Grosbach33c16a22011-07-14 22:04:21 +00004917 // If we had a carry-set on an instruction that can't do that, issue an
4918 // error.
4919 if (!CanAcceptCarrySet && CarrySetting) {
4920 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004921 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004922 "' can not set flags, but 's' suffix specified");
4923 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004924 // If we had a predication code on an instruction that can't do that, issue an
4925 // error.
4926 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4927 Parser.EatToEndOfStatement();
4928 return Error(NameLoc, "instruction '" + Mnemonic +
4929 "' is not predicable, but condition code specified");
4930 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004931
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004932 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004933 if (CanAcceptCarrySet) {
4934 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004935 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004936 Loc));
4937 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004938
4939 // Add the predication code operand, if necessary.
4940 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004941 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4942 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004943 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004944 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004945 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004946
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004947 // Add the processor imod operand, if necessary.
4948 if (ProcessorIMod) {
4949 Operands.push_back(ARMOperand::CreateImm(
4950 MCConstantExpr::Create(ProcessorIMod, getContext()),
4951 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004952 }
4953
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004954 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004955 while (Next != StringRef::npos) {
4956 Start = Next;
4957 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004958 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004959
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004960 // Some NEON instructions have an optional datatype suffix that is
4961 // completely ignored. Check for that.
4962 if (isDataTypeToken(ExtraToken) &&
4963 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4964 continue;
4965
Jim Grosbach81d2e392011-09-07 16:06:04 +00004966 if (ExtraToken != ".n") {
4967 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4968 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4969 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004970 }
4971
4972 // Read the remaining operands.
4973 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004974 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004975 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004976 Parser.EatToEndOfStatement();
4977 return true;
4978 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004979
4980 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004981 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004982
4983 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004984 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004985 Parser.EatToEndOfStatement();
4986 return true;
4987 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004988 }
4989 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004990
Chris Lattnercbf8a982010-09-11 16:18:25 +00004991 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004992 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004993 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004994 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004995 }
Bill Wendling146018f2010-11-06 21:42:12 +00004996
Chris Lattner34e53142010-09-08 05:10:46 +00004997 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004998
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004999 // Some instructions, mostly Thumb, have forms for the same mnemonic that
5000 // do and don't have a cc_out optional-def operand. With some spot-checks
5001 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00005002 // parse and adjust accordingly before actually matching. We shouldn't ever
5003 // try to remove a cc_out operand that was explicitly set on the the
5004 // mnemonic, of course (CarrySetting == true). Reason number #317 the
5005 // table driven matcher doesn't fit well with the ARM instruction set.
5006 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00005007 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
5008 Operands.erase(Operands.begin() + 1);
5009 delete Op;
5010 }
5011
Jim Grosbachcf121c32011-07-28 21:57:55 +00005012 // ARM mode 'blx' need special handling, as the register operand version
5013 // is predicable, but the label operand version is not. So, we can't rely
5014 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00005015 // a k_CondCode operand in the list. If we're trying to match the label
5016 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00005017 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
5018 static_cast<ARMOperand*>(Operands[2])->isImm()) {
5019 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
5020 Operands.erase(Operands.begin() + 1);
5021 delete Op;
5022 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00005023
5024 // The vector-compare-to-zero instructions have a literal token "#0" at
5025 // the end that comes to here as an immediate operand. Convert it to a
5026 // token to play nicely with the matcher.
5027 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
5028 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
5029 static_cast<ARMOperand*>(Operands[5])->isImm()) {
5030 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
5031 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
5032 if (CE && CE->getValue() == 0) {
5033 Operands.erase(Operands.begin() + 5);
5034 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5035 delete Op;
5036 }
5037 }
Jim Grosbach68259142011-10-03 22:30:24 +00005038 // VCMP{E} does the same thing, but with a different operand count.
5039 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
5040 static_cast<ARMOperand*>(Operands[4])->isImm()) {
5041 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
5042 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
5043 if (CE && CE->getValue() == 0) {
5044 Operands.erase(Operands.begin() + 4);
5045 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5046 delete Op;
5047 }
5048 }
Jim Grosbach934755a2011-08-22 23:47:13 +00005049 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
Jim Grosbach55b02f22011-12-13 20:50:38 +00005050 // end. Convert it to a token here. Take care not to convert those
5051 // that should hit the Thumb2 encoding.
Jim Grosbach934755a2011-08-22 23:47:13 +00005052 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
Jim Grosbach55b02f22011-12-13 20:50:38 +00005053 static_cast<ARMOperand*>(Operands[3])->isReg() &&
5054 static_cast<ARMOperand*>(Operands[4])->isReg() &&
Jim Grosbach934755a2011-08-22 23:47:13 +00005055 static_cast<ARMOperand*>(Operands[5])->isImm()) {
5056 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
5057 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
Jim Grosbach55b02f22011-12-13 20:50:38 +00005058 if (CE && CE->getValue() == 0 &&
5059 (isThumbOne() ||
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00005060 // The cc_out operand matches the IT block.
5061 ((inITBlock() != CarrySetting) &&
5062 // Neither register operand is a high register.
Jim Grosbach55b02f22011-12-13 20:50:38 +00005063 (isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00005064 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()))))){
Jim Grosbach934755a2011-08-22 23:47:13 +00005065 Operands.erase(Operands.begin() + 5);
5066 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5067 delete Op;
5068 }
5069 }
5070
Chris Lattner98986712010-01-14 22:21:20 +00005071 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005072}
5073
Jim Grosbach189610f2011-07-26 18:25:39 +00005074// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00005075
5076// return 'true' if register list contains non-low GPR registers,
5077// 'false' otherwise. If Reg is in the register list or is HiReg, set
5078// 'containsReg' to true.
5079static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
5080 unsigned HiReg, bool &containsReg) {
5081 containsReg = false;
5082 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5083 unsigned OpReg = Inst.getOperand(i).getReg();
5084 if (OpReg == Reg)
5085 containsReg = true;
5086 // Anything other than a low register isn't legal here.
5087 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
5088 return true;
5089 }
5090 return false;
5091}
5092
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005093// Check if the specified regisgter is in the register list of the inst,
5094// starting at the indicated operand number.
5095static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
5096 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5097 unsigned OpReg = Inst.getOperand(i).getReg();
5098 if (OpReg == Reg)
5099 return true;
5100 }
5101 return false;
5102}
5103
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005104// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
5105// the ARMInsts array) instead. Getting that here requires awkward
5106// API changes, though. Better way?
5107namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005108extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005109}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005110static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005111 return ARMInsts[Opcode];
5112}
5113
Jim Grosbach189610f2011-07-26 18:25:39 +00005114// FIXME: We would really like to be able to tablegen'erate this.
5115bool ARMAsmParser::
5116validateInstruction(MCInst &Inst,
5117 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005118 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005119 SMLoc Loc = Operands[0]->getStartLoc();
5120 // Check the IT block state first.
Jim Grosbach74423e32012-01-25 19:52:01 +00005121 // NOTE: BKPT instruction has the interesting property of being
5122 // allowed in IT blocks, but not being predicable. It just always
Owen Andersonb6b7f512011-09-13 17:59:19 +00005123 // executes.
Jim Grosbach74423e32012-01-25 19:52:01 +00005124 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT &&
5125 Inst.getOpcode() != ARM::BKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005126 unsigned bit = 1;
5127 if (ITState.FirstCond)
5128 ITState.FirstCond = false;
5129 else
Jim Grosbacha1109882011-09-02 23:22:08 +00005130 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005131 // The instruction must be predicable.
5132 if (!MCID.isPredicable())
5133 return Error(Loc, "instructions in IT block must be predicable");
5134 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
5135 unsigned ITCond = bit ? ITState.Cond :
5136 ARMCC::getOppositeCondition(ITState.Cond);
5137 if (Cond != ITCond) {
5138 // Find the condition code Operand to get its SMLoc information.
5139 SMLoc CondLoc;
5140 for (unsigned i = 1; i < Operands.size(); ++i)
5141 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
5142 CondLoc = Operands[i]->getStartLoc();
5143 return Error(CondLoc, "incorrect condition in IT block; got '" +
5144 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
5145 "', but expected '" +
5146 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
5147 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00005148 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005149 } else if (isThumbTwo() && MCID.isPredicable() &&
5150 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005151 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
5152 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005153 return Error(Loc, "predicated instructions must be in IT block");
5154
Jim Grosbach189610f2011-07-26 18:25:39 +00005155 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00005156 case ARM::LDRD:
5157 case ARM::LDRD_PRE:
5158 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005159 case ARM::LDREXD: {
5160 // Rt2 must be Rt + 1.
5161 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5162 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5163 if (Rt2 != Rt + 1)
5164 return Error(Operands[3]->getStartLoc(),
5165 "destination operands must be sequential");
5166 return false;
5167 }
Jim Grosbach14605d12011-08-11 20:28:23 +00005168 case ARM::STRD: {
5169 // Rt2 must be Rt + 1.
5170 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5171 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5172 if (Rt2 != Rt + 1)
5173 return Error(Operands[3]->getStartLoc(),
5174 "source operands must be sequential");
5175 return false;
5176 }
Jim Grosbach53642c52011-08-10 20:49:18 +00005177 case ARM::STRD_PRE:
5178 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005179 case ARM::STREXD: {
5180 // Rt2 must be Rt + 1.
5181 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5182 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
5183 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00005184 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00005185 "source operands must be sequential");
5186 return false;
5187 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005188 case ARM::SBFX:
5189 case ARM::UBFX: {
5190 // width must be in range [1, 32-lsb]
5191 unsigned lsb = Inst.getOperand(2).getImm();
5192 unsigned widthm1 = Inst.getOperand(3).getImm();
5193 if (widthm1 >= 32 - lsb)
5194 return Error(Operands[5]->getStartLoc(),
5195 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00005196 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005197 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005198 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005199 // If we're parsing Thumb2, the .w variant is available and handles
5200 // most cases that are normally illegal for a Thumb1 LDM
5201 // instruction. We'll make the transformation in processInstruction()
5202 // if necessary.
5203 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005204 // Thumb LDM instructions are writeback iff the base register is not
5205 // in the register list.
5206 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005207 bool hasWritebackToken =
5208 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5209 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00005210 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005211 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005212 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
5213 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005214 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005215 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005216 return Error(Operands[2]->getStartLoc(),
5217 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005218 // If we should not have writeback, there must not be a '!'. This is
5219 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00005220 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005221 return Error(Operands[3]->getStartLoc(),
5222 "writeback operator '!' not allowed when base register "
5223 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005224
5225 break;
5226 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005227 case ARM::t2LDMIA_UPD: {
5228 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
5229 return Error(Operands[4]->getStartLoc(),
5230 "writeback operator '!' not allowed when base register "
5231 "in register list");
5232 break;
5233 }
Jim Grosbach54026372011-11-10 23:17:11 +00005234 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
5235 // so only issue a diagnostic for thumb1. The instructions will be
5236 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005237 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005238 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005239 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
5240 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005241 return Error(Operands[2]->getStartLoc(),
5242 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005243 break;
5244 }
5245 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005246 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005247 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
5248 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005249 return Error(Operands[2]->getStartLoc(),
5250 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005251 break;
5252 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00005253 case ARM::tSTMIA_UPD: {
5254 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00005255 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00005256 return Error(Operands[4]->getStartLoc(),
5257 "registers must be in range r0-r7");
5258 break;
5259 }
Jim Grosbach189610f2011-07-26 18:25:39 +00005260 }
5261
5262 return false;
5263}
5264
Jim Grosbachd7433e22012-01-23 23:45:44 +00005265static unsigned getRealVSTOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach84defb52011-12-02 22:34:51 +00005266 switch(Opc) {
Craig Topperbc219812012-02-07 02:50:20 +00005267 default: llvm_unreachable("unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005268 // VST1LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005269 case ARM::VST1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
5270 case ARM::VST1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
5271 case ARM::VST1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
5272 case ARM::VST1LNdWB_register_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
5273 case ARM::VST1LNdWB_register_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
5274 case ARM::VST1LNdWB_register_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
5275 case ARM::VST1LNdAsm_8: Spacing = 1; return ARM::VST1LNd8;
5276 case ARM::VST1LNdAsm_16: Spacing = 1; return ARM::VST1LNd16;
5277 case ARM::VST1LNdAsm_32: Spacing = 1; return ARM::VST1LNd32;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005278
5279 // VST2LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005280 case ARM::VST2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
5281 case ARM::VST2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
5282 case ARM::VST2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
5283 case ARM::VST2LNqWB_fixed_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
5284 case ARM::VST2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005285
Jim Grosbach7945ead2012-01-24 00:43:12 +00005286 case ARM::VST2LNdWB_register_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
5287 case ARM::VST2LNdWB_register_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
5288 case ARM::VST2LNdWB_register_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
5289 case ARM::VST2LNqWB_register_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
5290 case ARM::VST2LNqWB_register_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005291
Jim Grosbach7945ead2012-01-24 00:43:12 +00005292 case ARM::VST2LNdAsm_8: Spacing = 1; return ARM::VST2LNd8;
5293 case ARM::VST2LNdAsm_16: Spacing = 1; return ARM::VST2LNd16;
5294 case ARM::VST2LNdAsm_32: Spacing = 1; return ARM::VST2LNd32;
5295 case ARM::VST2LNqAsm_16: Spacing = 2; return ARM::VST2LNq16;
5296 case ARM::VST2LNqAsm_32: Spacing = 2; return ARM::VST2LNq32;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005297
Jim Grosbach4adb1822012-01-24 00:07:41 +00005298 // VST3LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005299 case ARM::VST3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
5300 case ARM::VST3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
5301 case ARM::VST3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
5302 case ARM::VST3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNq16_UPD;
5303 case ARM::VST3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
5304 case ARM::VST3LNdWB_register_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
5305 case ARM::VST3LNdWB_register_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
5306 case ARM::VST3LNdWB_register_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
5307 case ARM::VST3LNqWB_register_Asm_16: Spacing = 2; return ARM::VST3LNq16_UPD;
5308 case ARM::VST3LNqWB_register_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
5309 case ARM::VST3LNdAsm_8: Spacing = 1; return ARM::VST3LNd8;
5310 case ARM::VST3LNdAsm_16: Spacing = 1; return ARM::VST3LNd16;
5311 case ARM::VST3LNdAsm_32: Spacing = 1; return ARM::VST3LNd32;
5312 case ARM::VST3LNqAsm_16: Spacing = 2; return ARM::VST3LNq16;
5313 case ARM::VST3LNqAsm_32: Spacing = 2; return ARM::VST3LNq32;
Jim Grosbach4adb1822012-01-24 00:07:41 +00005314
Jim Grosbachd7433e22012-01-23 23:45:44 +00005315 // VST3
Jim Grosbach7945ead2012-01-24 00:43:12 +00005316 case ARM::VST3dWB_fixed_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
5317 case ARM::VST3dWB_fixed_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
5318 case ARM::VST3dWB_fixed_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
5319 case ARM::VST3qWB_fixed_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
5320 case ARM::VST3qWB_fixed_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
5321 case ARM::VST3qWB_fixed_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
5322 case ARM::VST3dWB_register_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
5323 case ARM::VST3dWB_register_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
5324 case ARM::VST3dWB_register_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
5325 case ARM::VST3qWB_register_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
5326 case ARM::VST3qWB_register_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
5327 case ARM::VST3qWB_register_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
5328 case ARM::VST3dAsm_8: Spacing = 1; return ARM::VST3d8;
5329 case ARM::VST3dAsm_16: Spacing = 1; return ARM::VST3d16;
5330 case ARM::VST3dAsm_32: Spacing = 1; return ARM::VST3d32;
5331 case ARM::VST3qAsm_8: Spacing = 2; return ARM::VST3q8;
5332 case ARM::VST3qAsm_16: Spacing = 2; return ARM::VST3q16;
5333 case ARM::VST3qAsm_32: Spacing = 2; return ARM::VST3q32;
Jim Grosbach539aab72012-01-24 00:58:13 +00005334
Jim Grosbach88a54de2012-01-24 18:53:13 +00005335 // VST4LN
5336 case ARM::VST4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD;
5337 case ARM::VST4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD;
5338 case ARM::VST4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD;
5339 case ARM::VST4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNq16_UPD;
5340 case ARM::VST4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD;
5341 case ARM::VST4LNdWB_register_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD;
5342 case ARM::VST4LNdWB_register_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD;
5343 case ARM::VST4LNdWB_register_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD;
5344 case ARM::VST4LNqWB_register_Asm_16: Spacing = 2; return ARM::VST4LNq16_UPD;
5345 case ARM::VST4LNqWB_register_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD;
5346 case ARM::VST4LNdAsm_8: Spacing = 1; return ARM::VST4LNd8;
5347 case ARM::VST4LNdAsm_16: Spacing = 1; return ARM::VST4LNd16;
5348 case ARM::VST4LNdAsm_32: Spacing = 1; return ARM::VST4LNd32;
5349 case ARM::VST4LNqAsm_16: Spacing = 2; return ARM::VST4LNq16;
5350 case ARM::VST4LNqAsm_32: Spacing = 2; return ARM::VST4LNq32;
5351
Jim Grosbach539aab72012-01-24 00:58:13 +00005352 // VST4
5353 case ARM::VST4dWB_fixed_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
5354 case ARM::VST4dWB_fixed_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
5355 case ARM::VST4dWB_fixed_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
5356 case ARM::VST4qWB_fixed_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
5357 case ARM::VST4qWB_fixed_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
5358 case ARM::VST4qWB_fixed_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
5359 case ARM::VST4dWB_register_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
5360 case ARM::VST4dWB_register_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
5361 case ARM::VST4dWB_register_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
5362 case ARM::VST4qWB_register_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
5363 case ARM::VST4qWB_register_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
5364 case ARM::VST4qWB_register_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
5365 case ARM::VST4dAsm_8: Spacing = 1; return ARM::VST4d8;
5366 case ARM::VST4dAsm_16: Spacing = 1; return ARM::VST4d16;
5367 case ARM::VST4dAsm_32: Spacing = 1; return ARM::VST4d32;
5368 case ARM::VST4qAsm_8: Spacing = 2; return ARM::VST4q8;
5369 case ARM::VST4qAsm_16: Spacing = 2; return ARM::VST4q16;
5370 case ARM::VST4qAsm_32: Spacing = 2; return ARM::VST4q32;
Jim Grosbach84defb52011-12-02 22:34:51 +00005371 }
5372}
5373
Jim Grosbachd7433e22012-01-23 23:45:44 +00005374static unsigned getRealVLDOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005375 switch(Opc) {
Craig Topperbc219812012-02-07 02:50:20 +00005376 default: llvm_unreachable("unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005377 // VLD1LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005378 case ARM::VLD1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
5379 case ARM::VLD1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
5380 case ARM::VLD1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
5381 case ARM::VLD1LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
5382 case ARM::VLD1LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
5383 case ARM::VLD1LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
5384 case ARM::VLD1LNdAsm_8: Spacing = 1; return ARM::VLD1LNd8;
5385 case ARM::VLD1LNdAsm_16: Spacing = 1; return ARM::VLD1LNd16;
5386 case ARM::VLD1LNdAsm_32: Spacing = 1; return ARM::VLD1LNd32;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005387
5388 // VLD2LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005389 case ARM::VLD2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
5390 case ARM::VLD2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
5391 case ARM::VLD2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
5392 case ARM::VLD2LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNq16_UPD;
5393 case ARM::VLD2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
5394 case ARM::VLD2LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
5395 case ARM::VLD2LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
5396 case ARM::VLD2LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
5397 case ARM::VLD2LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD2LNq16_UPD;
5398 case ARM::VLD2LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
5399 case ARM::VLD2LNdAsm_8: Spacing = 1; return ARM::VLD2LNd8;
5400 case ARM::VLD2LNdAsm_16: Spacing = 1; return ARM::VLD2LNd16;
5401 case ARM::VLD2LNdAsm_32: Spacing = 1; return ARM::VLD2LNd32;
5402 case ARM::VLD2LNqAsm_16: Spacing = 2; return ARM::VLD2LNq16;
5403 case ARM::VLD2LNqAsm_32: Spacing = 2; return ARM::VLD2LNq32;
Jim Grosbach3a678af2012-01-23 21:53:26 +00005404
Jim Grosbach5e59f7e2012-01-24 23:47:04 +00005405 // VLD3DUP
5406 case ARM::VLD3DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD;
5407 case ARM::VLD3DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD;
5408 case ARM::VLD3DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD;
5409 case ARM::VLD3DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPq8_UPD;
5410 case ARM::VLD3DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPq16_UPD;
5411 case ARM::VLD3DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD;
5412 case ARM::VLD3DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD;
5413 case ARM::VLD3DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD;
5414 case ARM::VLD3DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD;
5415 case ARM::VLD3DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD3DUPq8_UPD;
5416 case ARM::VLD3DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD3DUPq16_UPD;
5417 case ARM::VLD3DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD;
5418 case ARM::VLD3DUPdAsm_8: Spacing = 1; return ARM::VLD3DUPd8;
5419 case ARM::VLD3DUPdAsm_16: Spacing = 1; return ARM::VLD3DUPd16;
5420 case ARM::VLD3DUPdAsm_32: Spacing = 1; return ARM::VLD3DUPd32;
5421 case ARM::VLD3DUPqAsm_8: Spacing = 2; return ARM::VLD3DUPq8;
5422 case ARM::VLD3DUPqAsm_16: Spacing = 2; return ARM::VLD3DUPq16;
5423 case ARM::VLD3DUPqAsm_32: Spacing = 2; return ARM::VLD3DUPq32;
5424
Jim Grosbach3a678af2012-01-23 21:53:26 +00005425 // VLD3LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005426 case ARM::VLD3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
5427 case ARM::VLD3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
5428 case ARM::VLD3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
5429 case ARM::VLD3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNq16_UPD;
5430 case ARM::VLD3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
5431 case ARM::VLD3LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
5432 case ARM::VLD3LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
5433 case ARM::VLD3LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
5434 case ARM::VLD3LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD3LNq16_UPD;
5435 case ARM::VLD3LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
5436 case ARM::VLD3LNdAsm_8: Spacing = 1; return ARM::VLD3LNd8;
5437 case ARM::VLD3LNdAsm_16: Spacing = 1; return ARM::VLD3LNd16;
5438 case ARM::VLD3LNdAsm_32: Spacing = 1; return ARM::VLD3LNd32;
5439 case ARM::VLD3LNqAsm_16: Spacing = 2; return ARM::VLD3LNq16;
5440 case ARM::VLD3LNqAsm_32: Spacing = 2; return ARM::VLD3LNq32;
Jim Grosbachc387fc62012-01-23 23:20:46 +00005441
5442 // VLD3
Jim Grosbach7945ead2012-01-24 00:43:12 +00005443 case ARM::VLD3dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
5444 case ARM::VLD3dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
5445 case ARM::VLD3dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
5446 case ARM::VLD3qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
5447 case ARM::VLD3qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
5448 case ARM::VLD3qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
5449 case ARM::VLD3dWB_register_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
5450 case ARM::VLD3dWB_register_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
5451 case ARM::VLD3dWB_register_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
5452 case ARM::VLD3qWB_register_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
5453 case ARM::VLD3qWB_register_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
5454 case ARM::VLD3qWB_register_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
5455 case ARM::VLD3dAsm_8: Spacing = 1; return ARM::VLD3d8;
5456 case ARM::VLD3dAsm_16: Spacing = 1; return ARM::VLD3d16;
5457 case ARM::VLD3dAsm_32: Spacing = 1; return ARM::VLD3d32;
5458 case ARM::VLD3qAsm_8: Spacing = 2; return ARM::VLD3q8;
5459 case ARM::VLD3qAsm_16: Spacing = 2; return ARM::VLD3q16;
5460 case ARM::VLD3qAsm_32: Spacing = 2; return ARM::VLD3q32;
Jim Grosbach8abe7e32012-01-24 00:43:17 +00005461
Jim Grosbache983a132012-01-24 18:37:25 +00005462 // VLD4LN
5463 case ARM::VLD4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD;
5464 case ARM::VLD4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
5465 case ARM::VLD4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
5466 case ARM::VLD4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNq16_UPD;
5467 case ARM::VLD4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
5468 case ARM::VLD4LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD;
5469 case ARM::VLD4LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
5470 case ARM::VLD4LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
5471 case ARM::VLD4LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD4LNq16_UPD;
5472 case ARM::VLD4LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
5473 case ARM::VLD4LNdAsm_8: Spacing = 1; return ARM::VLD4LNd8;
5474 case ARM::VLD4LNdAsm_16: Spacing = 1; return ARM::VLD4LNd16;
5475 case ARM::VLD4LNdAsm_32: Spacing = 1; return ARM::VLD4LNd32;
5476 case ARM::VLD4LNqAsm_16: Spacing = 2; return ARM::VLD4LNq16;
5477 case ARM::VLD4LNqAsm_32: Spacing = 2; return ARM::VLD4LNq32;
5478
Jim Grosbacha57a36a2012-01-25 00:01:08 +00005479 // VLD4DUP
5480 case ARM::VLD4DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD;
5481 case ARM::VLD4DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD;
5482 case ARM::VLD4DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD;
5483 case ARM::VLD4DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPq8_UPD;
5484 case ARM::VLD4DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPq16_UPD;
5485 case ARM::VLD4DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD;
5486 case ARM::VLD4DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD;
5487 case ARM::VLD4DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD;
5488 case ARM::VLD4DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD;
5489 case ARM::VLD4DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD4DUPq8_UPD;
5490 case ARM::VLD4DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD4DUPq16_UPD;
5491 case ARM::VLD4DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD;
5492 case ARM::VLD4DUPdAsm_8: Spacing = 1; return ARM::VLD4DUPd8;
5493 case ARM::VLD4DUPdAsm_16: Spacing = 1; return ARM::VLD4DUPd16;
5494 case ARM::VLD4DUPdAsm_32: Spacing = 1; return ARM::VLD4DUPd32;
5495 case ARM::VLD4DUPqAsm_8: Spacing = 2; return ARM::VLD4DUPq8;
5496 case ARM::VLD4DUPqAsm_16: Spacing = 2; return ARM::VLD4DUPq16;
5497 case ARM::VLD4DUPqAsm_32: Spacing = 2; return ARM::VLD4DUPq32;
5498
Jim Grosbach8abe7e32012-01-24 00:43:17 +00005499 // VLD4
5500 case ARM::VLD4dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
5501 case ARM::VLD4dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
5502 case ARM::VLD4dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
5503 case ARM::VLD4qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
5504 case ARM::VLD4qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
5505 case ARM::VLD4qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
5506 case ARM::VLD4dWB_register_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
5507 case ARM::VLD4dWB_register_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
5508 case ARM::VLD4dWB_register_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
5509 case ARM::VLD4qWB_register_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
5510 case ARM::VLD4qWB_register_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
5511 case ARM::VLD4qWB_register_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
5512 case ARM::VLD4dAsm_8: Spacing = 1; return ARM::VLD4d8;
5513 case ARM::VLD4dAsm_16: Spacing = 1; return ARM::VLD4d16;
5514 case ARM::VLD4dAsm_32: Spacing = 1; return ARM::VLD4d32;
5515 case ARM::VLD4qAsm_8: Spacing = 2; return ARM::VLD4q8;
5516 case ARM::VLD4qAsm_16: Spacing = 2; return ARM::VLD4q16;
5517 case ARM::VLD4qAsm_32: Spacing = 2; return ARM::VLD4q32;
Jim Grosbach7636bf62011-12-02 00:35:16 +00005518 }
5519}
5520
Jim Grosbach83ec8772011-11-10 23:42:14 +00005521bool ARMAsmParser::
Jim Grosbachf8fce712011-08-11 17:35:48 +00005522processInstruction(MCInst &Inst,
5523 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5524 switch (Inst.getOpcode()) {
Jim Grosbach0b4c6732012-01-18 22:46:46 +00005525 // Aliases for alternate PC+imm syntax of LDR instructions.
5526 case ARM::t2LDRpcrel:
5527 Inst.setOpcode(ARM::t2LDRpci);
5528 return true;
5529 case ARM::t2LDRBpcrel:
5530 Inst.setOpcode(ARM::t2LDRBpci);
5531 return true;
5532 case ARM::t2LDRHpcrel:
5533 Inst.setOpcode(ARM::t2LDRHpci);
5534 return true;
5535 case ARM::t2LDRSBpcrel:
5536 Inst.setOpcode(ARM::t2LDRSBpci);
5537 return true;
5538 case ARM::t2LDRSHpcrel:
5539 Inst.setOpcode(ARM::t2LDRSHpci);
5540 return true;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005541 // Handle NEON VST complex aliases.
Jim Grosbach8b31f952012-01-23 19:39:08 +00005542 case ARM::VST1LNdWB_register_Asm_8:
5543 case ARM::VST1LNdWB_register_Asm_16:
5544 case ARM::VST1LNdWB_register_Asm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005545 MCInst TmpInst;
5546 // Shuffle the operands around so the lane index operand is in the
5547 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005548 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005549 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005550 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5551 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5552 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5553 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5554 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5555 TmpInst.addOperand(Inst.getOperand(1)); // lane
5556 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5557 TmpInst.addOperand(Inst.getOperand(6));
5558 Inst = TmpInst;
5559 return true;
5560 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005561
Jim Grosbach8b31f952012-01-23 19:39:08 +00005562 case ARM::VST2LNdWB_register_Asm_8:
5563 case ARM::VST2LNdWB_register_Asm_16:
5564 case ARM::VST2LNdWB_register_Asm_32:
5565 case ARM::VST2LNqWB_register_Asm_16:
5566 case ARM::VST2LNqWB_register_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005567 MCInst TmpInst;
5568 // Shuffle the operands around so the lane index operand is in the
5569 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005570 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005571 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005572 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5573 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5574 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5575 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5576 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005577 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5578 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005579 TmpInst.addOperand(Inst.getOperand(1)); // lane
5580 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5581 TmpInst.addOperand(Inst.getOperand(6));
5582 Inst = TmpInst;
5583 return true;
5584 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005585
5586 case ARM::VST3LNdWB_register_Asm_8:
5587 case ARM::VST3LNdWB_register_Asm_16:
5588 case ARM::VST3LNdWB_register_Asm_32:
5589 case ARM::VST3LNqWB_register_Asm_16:
5590 case ARM::VST3LNqWB_register_Asm_32: {
5591 MCInst TmpInst;
5592 // Shuffle the operands around so the lane index operand is in the
5593 // right place.
5594 unsigned Spacing;
5595 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5596 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5597 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5598 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5599 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5600 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5601 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5602 Spacing));
5603 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5604 Spacing * 2));
5605 TmpInst.addOperand(Inst.getOperand(1)); // lane
5606 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5607 TmpInst.addOperand(Inst.getOperand(6));
5608 Inst = TmpInst;
5609 return true;
5610 }
5611
Jim Grosbach88a54de2012-01-24 18:53:13 +00005612 case ARM::VST4LNdWB_register_Asm_8:
5613 case ARM::VST4LNdWB_register_Asm_16:
5614 case ARM::VST4LNdWB_register_Asm_32:
5615 case ARM::VST4LNqWB_register_Asm_16:
5616 case ARM::VST4LNqWB_register_Asm_32: {
5617 MCInst TmpInst;
5618 // Shuffle the operands around so the lane index operand is in the
5619 // right place.
5620 unsigned Spacing;
5621 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5622 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5623 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5624 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5625 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5626 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5627 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5628 Spacing));
5629 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5630 Spacing * 2));
5631 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5632 Spacing * 3));
5633 TmpInst.addOperand(Inst.getOperand(1)); // lane
5634 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5635 TmpInst.addOperand(Inst.getOperand(6));
5636 Inst = TmpInst;
5637 return true;
5638 }
5639
Jim Grosbach8b31f952012-01-23 19:39:08 +00005640 case ARM::VST1LNdWB_fixed_Asm_8:
5641 case ARM::VST1LNdWB_fixed_Asm_16:
5642 case ARM::VST1LNdWB_fixed_Asm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005643 MCInst TmpInst;
5644 // Shuffle the operands around so the lane index operand is in the
5645 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005646 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005647 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005648 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5649 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5650 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5651 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5652 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5653 TmpInst.addOperand(Inst.getOperand(1)); // lane
5654 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5655 TmpInst.addOperand(Inst.getOperand(5));
5656 Inst = TmpInst;
5657 return true;
5658 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005659
Jim Grosbach8b31f952012-01-23 19:39:08 +00005660 case ARM::VST2LNdWB_fixed_Asm_8:
5661 case ARM::VST2LNdWB_fixed_Asm_16:
5662 case ARM::VST2LNdWB_fixed_Asm_32:
5663 case ARM::VST2LNqWB_fixed_Asm_16:
5664 case ARM::VST2LNqWB_fixed_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005665 MCInst TmpInst;
5666 // Shuffle the operands around so the lane index operand is in the
5667 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005668 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005669 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005670 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5671 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5672 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5673 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5674 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005675 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5676 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005677 TmpInst.addOperand(Inst.getOperand(1)); // lane
5678 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5679 TmpInst.addOperand(Inst.getOperand(5));
5680 Inst = TmpInst;
5681 return true;
5682 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005683
5684 case ARM::VST3LNdWB_fixed_Asm_8:
5685 case ARM::VST3LNdWB_fixed_Asm_16:
5686 case ARM::VST3LNdWB_fixed_Asm_32:
5687 case ARM::VST3LNqWB_fixed_Asm_16:
5688 case ARM::VST3LNqWB_fixed_Asm_32: {
5689 MCInst TmpInst;
5690 // Shuffle the operands around so the lane index operand is in the
5691 // right place.
5692 unsigned Spacing;
5693 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5694 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5695 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5696 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5697 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5698 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5699 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5700 Spacing));
5701 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5702 Spacing * 2));
5703 TmpInst.addOperand(Inst.getOperand(1)); // lane
5704 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5705 TmpInst.addOperand(Inst.getOperand(5));
5706 Inst = TmpInst;
5707 return true;
5708 }
5709
Jim Grosbach88a54de2012-01-24 18:53:13 +00005710 case ARM::VST4LNdWB_fixed_Asm_8:
5711 case ARM::VST4LNdWB_fixed_Asm_16:
5712 case ARM::VST4LNdWB_fixed_Asm_32:
5713 case ARM::VST4LNqWB_fixed_Asm_16:
5714 case ARM::VST4LNqWB_fixed_Asm_32: {
5715 MCInst TmpInst;
5716 // Shuffle the operands around so the lane index operand is in the
5717 // right place.
5718 unsigned Spacing;
5719 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5720 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5721 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5722 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5723 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5724 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5725 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5726 Spacing));
5727 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5728 Spacing * 2));
5729 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5730 Spacing * 3));
5731 TmpInst.addOperand(Inst.getOperand(1)); // lane
5732 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5733 TmpInst.addOperand(Inst.getOperand(5));
5734 Inst = TmpInst;
5735 return true;
5736 }
5737
Jim Grosbach8b31f952012-01-23 19:39:08 +00005738 case ARM::VST1LNdAsm_8:
5739 case ARM::VST1LNdAsm_16:
5740 case ARM::VST1LNdAsm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005741 MCInst TmpInst;
5742 // Shuffle the operands around so the lane index operand is in the
5743 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005744 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005745 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005746 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5747 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5748 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5749 TmpInst.addOperand(Inst.getOperand(1)); // lane
5750 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5751 TmpInst.addOperand(Inst.getOperand(5));
5752 Inst = TmpInst;
5753 return true;
5754 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005755
Jim Grosbach8b31f952012-01-23 19:39:08 +00005756 case ARM::VST2LNdAsm_8:
5757 case ARM::VST2LNdAsm_16:
5758 case ARM::VST2LNdAsm_32:
5759 case ARM::VST2LNqAsm_16:
5760 case ARM::VST2LNqAsm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005761 MCInst TmpInst;
5762 // Shuffle the operands around so the lane index operand is in the
5763 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005764 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005765 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005766 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5767 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5768 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005769 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5770 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005771 TmpInst.addOperand(Inst.getOperand(1)); // lane
5772 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5773 TmpInst.addOperand(Inst.getOperand(5));
5774 Inst = TmpInst;
5775 return true;
5776 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005777
5778 case ARM::VST3LNdAsm_8:
5779 case ARM::VST3LNdAsm_16:
5780 case ARM::VST3LNdAsm_32:
5781 case ARM::VST3LNqAsm_16:
5782 case ARM::VST3LNqAsm_32: {
5783 MCInst TmpInst;
5784 // Shuffle the operands around so the lane index operand is in the
5785 // right place.
5786 unsigned Spacing;
5787 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5788 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5789 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5790 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)); // lane
5796 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5797 TmpInst.addOperand(Inst.getOperand(5));
5798 Inst = TmpInst;
5799 return true;
5800 }
5801
Jim Grosbach88a54de2012-01-24 18:53:13 +00005802 case ARM::VST4LNdAsm_8:
5803 case ARM::VST4LNdAsm_16:
5804 case ARM::VST4LNdAsm_32:
5805 case ARM::VST4LNqAsm_16:
5806 case ARM::VST4LNqAsm_32: {
5807 MCInst TmpInst;
5808 // Shuffle the operands around so the lane index operand is in the
5809 // right place.
5810 unsigned Spacing;
5811 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5812 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5813 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5814 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5815 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5816 Spacing));
5817 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5818 Spacing * 2));
5819 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5820 Spacing * 3));
5821 TmpInst.addOperand(Inst.getOperand(1)); // lane
5822 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5823 TmpInst.addOperand(Inst.getOperand(5));
5824 Inst = TmpInst;
5825 return true;
5826 }
5827
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005828 // Handle NEON VLD complex aliases.
Jim Grosbach8b31f952012-01-23 19:39:08 +00005829 case ARM::VLD1LNdWB_register_Asm_8:
5830 case ARM::VLD1LNdWB_register_Asm_16:
5831 case ARM::VLD1LNdWB_register_Asm_32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005832 MCInst TmpInst;
5833 // Shuffle the operands around so the lane index operand is in the
5834 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005835 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005836 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005837 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5838 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5839 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5840 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5841 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5842 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5843 TmpInst.addOperand(Inst.getOperand(1)); // lane
5844 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5845 TmpInst.addOperand(Inst.getOperand(6));
5846 Inst = TmpInst;
5847 return true;
5848 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005849
Jim Grosbach8b31f952012-01-23 19:39:08 +00005850 case ARM::VLD2LNdWB_register_Asm_8:
5851 case ARM::VLD2LNdWB_register_Asm_16:
5852 case ARM::VLD2LNdWB_register_Asm_32:
5853 case ARM::VLD2LNqWB_register_Asm_16:
5854 case ARM::VLD2LNqWB_register_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005855 MCInst TmpInst;
5856 // Shuffle the operands around so the lane index operand is in the
5857 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005858 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005859 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005860 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005861 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5862 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005863 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5864 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5865 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5866 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5867 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005868 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5869 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005870 TmpInst.addOperand(Inst.getOperand(1)); // lane
5871 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5872 TmpInst.addOperand(Inst.getOperand(6));
5873 Inst = TmpInst;
5874 return true;
5875 }
5876
Jim Grosbach3a678af2012-01-23 21:53:26 +00005877 case ARM::VLD3LNdWB_register_Asm_8:
5878 case ARM::VLD3LNdWB_register_Asm_16:
5879 case ARM::VLD3LNdWB_register_Asm_32:
5880 case ARM::VLD3LNqWB_register_Asm_16:
5881 case ARM::VLD3LNqWB_register_Asm_32: {
5882 MCInst TmpInst;
5883 // Shuffle the operands around so the lane index operand is in the
5884 // right place.
5885 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005886 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005887 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() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005891 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005892 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5893 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5894 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5895 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5896 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5897 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5898 Spacing));
5899 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005900 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005901 TmpInst.addOperand(Inst.getOperand(1)); // lane
5902 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5903 TmpInst.addOperand(Inst.getOperand(6));
5904 Inst = TmpInst;
5905 return true;
5906 }
5907
Jim Grosbache983a132012-01-24 18:37:25 +00005908 case ARM::VLD4LNdWB_register_Asm_8:
5909 case ARM::VLD4LNdWB_register_Asm_16:
5910 case ARM::VLD4LNdWB_register_Asm_32:
5911 case ARM::VLD4LNqWB_register_Asm_16:
5912 case ARM::VLD4LNqWB_register_Asm_32: {
5913 MCInst TmpInst;
5914 // Shuffle the operands around so the lane index operand is in the
5915 // right place.
5916 unsigned Spacing;
5917 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
5918 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5919 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5920 Spacing));
5921 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5922 Spacing * 2));
5923 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5924 Spacing * 3));
5925 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5926 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5927 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5928 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5929 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5930 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5931 Spacing));
5932 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5933 Spacing * 2));
5934 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5935 Spacing * 3));
5936 TmpInst.addOperand(Inst.getOperand(1)); // lane
5937 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5938 TmpInst.addOperand(Inst.getOperand(6));
5939 Inst = TmpInst;
5940 return true;
5941 }
5942
Jim Grosbach8b31f952012-01-23 19:39:08 +00005943 case ARM::VLD1LNdWB_fixed_Asm_8:
5944 case ARM::VLD1LNdWB_fixed_Asm_16:
5945 case ARM::VLD1LNdWB_fixed_Asm_32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005946 MCInst TmpInst;
5947 // Shuffle the operands around so the lane index operand is in the
5948 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005949 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005950 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005951 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5952 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5953 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5954 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5955 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5956 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5957 TmpInst.addOperand(Inst.getOperand(1)); // lane
5958 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5959 TmpInst.addOperand(Inst.getOperand(5));
5960 Inst = TmpInst;
5961 return true;
5962 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005963
Jim Grosbach8b31f952012-01-23 19:39:08 +00005964 case ARM::VLD2LNdWB_fixed_Asm_8:
5965 case ARM::VLD2LNdWB_fixed_Asm_16:
5966 case ARM::VLD2LNdWB_fixed_Asm_32:
5967 case ARM::VLD2LNqWB_fixed_Asm_16:
5968 case ARM::VLD2LNqWB_fixed_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005969 MCInst TmpInst;
5970 // Shuffle the operands around so the lane index operand is in the
5971 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005972 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005973 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005974 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005975 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5976 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005977 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5978 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5979 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5980 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5981 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005982 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5983 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005984 TmpInst.addOperand(Inst.getOperand(1)); // lane
5985 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5986 TmpInst.addOperand(Inst.getOperand(5));
5987 Inst = TmpInst;
5988 return true;
5989 }
5990
Jim Grosbach3a678af2012-01-23 21:53:26 +00005991 case ARM::VLD3LNdWB_fixed_Asm_8:
5992 case ARM::VLD3LNdWB_fixed_Asm_16:
5993 case ARM::VLD3LNdWB_fixed_Asm_32:
5994 case ARM::VLD3LNqWB_fixed_Asm_16:
5995 case ARM::VLD3LNqWB_fixed_Asm_32: {
5996 MCInst TmpInst;
5997 // Shuffle the operands around so the lane index operand is in the
5998 // right place.
5999 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006000 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006001 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6002 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6003 Spacing));
6004 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006005 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006006 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6007 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6008 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6009 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6010 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6011 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6012 Spacing));
6013 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006014 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006015 TmpInst.addOperand(Inst.getOperand(1)); // lane
6016 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6017 TmpInst.addOperand(Inst.getOperand(5));
6018 Inst = TmpInst;
6019 return true;
6020 }
6021
Jim Grosbache983a132012-01-24 18:37:25 +00006022 case ARM::VLD4LNdWB_fixed_Asm_8:
6023 case ARM::VLD4LNdWB_fixed_Asm_16:
6024 case ARM::VLD4LNdWB_fixed_Asm_32:
6025 case ARM::VLD4LNqWB_fixed_Asm_16:
6026 case ARM::VLD4LNqWB_fixed_Asm_32: {
6027 MCInst TmpInst;
6028 // Shuffle the operands around so the lane index operand is in the
6029 // right place.
6030 unsigned Spacing;
6031 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6032 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6033 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6034 Spacing));
6035 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6036 Spacing * 2));
6037 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6038 Spacing * 3));
6039 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6040 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6041 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6042 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6043 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6044 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6045 Spacing));
6046 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6047 Spacing * 2));
6048 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6049 Spacing * 3));
6050 TmpInst.addOperand(Inst.getOperand(1)); // lane
6051 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6052 TmpInst.addOperand(Inst.getOperand(5));
6053 Inst = TmpInst;
6054 return true;
6055 }
6056
Jim Grosbach8b31f952012-01-23 19:39:08 +00006057 case ARM::VLD1LNdAsm_8:
6058 case ARM::VLD1LNdAsm_16:
6059 case ARM::VLD1LNdAsm_32: {
Jim Grosbach7636bf62011-12-02 00:35:16 +00006060 MCInst TmpInst;
6061 // Shuffle the operands around so the lane index operand is in the
6062 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006063 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006064 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach7636bf62011-12-02 00:35:16 +00006065 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6066 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6067 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6068 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6069 TmpInst.addOperand(Inst.getOperand(1)); // lane
6070 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6071 TmpInst.addOperand(Inst.getOperand(5));
6072 Inst = TmpInst;
6073 return true;
6074 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006075
Jim Grosbach8b31f952012-01-23 19:39:08 +00006076 case ARM::VLD2LNdAsm_8:
6077 case ARM::VLD2LNdAsm_16:
6078 case ARM::VLD2LNdAsm_32:
6079 case ARM::VLD2LNqAsm_16:
6080 case ARM::VLD2LNqAsm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006081 MCInst TmpInst;
6082 // Shuffle the operands around so the lane index operand is in the
6083 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006084 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006085 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006086 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006087 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6088 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006089 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6090 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6091 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006092 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6093 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006094 TmpInst.addOperand(Inst.getOperand(1)); // lane
6095 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6096 TmpInst.addOperand(Inst.getOperand(5));
6097 Inst = TmpInst;
6098 return true;
6099 }
Jim Grosbach3a678af2012-01-23 21:53:26 +00006100
6101 case ARM::VLD3LNdAsm_8:
6102 case ARM::VLD3LNdAsm_16:
6103 case ARM::VLD3LNdAsm_32:
6104 case ARM::VLD3LNqAsm_16:
6105 case ARM::VLD3LNqAsm_32: {
6106 MCInst TmpInst;
6107 // Shuffle the operands around so the lane index operand is in the
6108 // right place.
6109 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006110 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006111 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6112 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6113 Spacing));
6114 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006115 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006116 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6117 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6118 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6119 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6120 Spacing));
6121 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006122 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006123 TmpInst.addOperand(Inst.getOperand(1)); // lane
6124 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6125 TmpInst.addOperand(Inst.getOperand(5));
6126 Inst = TmpInst;
6127 return true;
6128 }
6129
Jim Grosbache983a132012-01-24 18:37:25 +00006130 case ARM::VLD4LNdAsm_8:
6131 case ARM::VLD4LNdAsm_16:
6132 case ARM::VLD4LNdAsm_32:
6133 case ARM::VLD4LNqAsm_16:
6134 case ARM::VLD4LNqAsm_32: {
6135 MCInst TmpInst;
6136 // Shuffle the operands around so the lane index operand is in the
6137 // right place.
6138 unsigned Spacing;
6139 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6140 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6141 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6142 Spacing));
6143 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6144 Spacing * 2));
6145 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6146 Spacing * 3));
6147 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6148 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6149 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6150 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6151 Spacing));
6152 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6153 Spacing * 2));
6154 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6155 Spacing * 3));
6156 TmpInst.addOperand(Inst.getOperand(1)); // lane
6157 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6158 TmpInst.addOperand(Inst.getOperand(5));
6159 Inst = TmpInst;
6160 return true;
6161 }
6162
Jim Grosbach5e59f7e2012-01-24 23:47:04 +00006163 // VLD3DUP single 3-element structure to all lanes instructions.
6164 case ARM::VLD3DUPdAsm_8:
6165 case ARM::VLD3DUPdAsm_16:
6166 case ARM::VLD3DUPdAsm_32:
6167 case ARM::VLD3DUPqAsm_8:
6168 case ARM::VLD3DUPqAsm_16:
6169 case ARM::VLD3DUPqAsm_32: {
6170 MCInst TmpInst;
6171 unsigned Spacing;
6172 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6173 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6174 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6175 Spacing));
6176 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6177 Spacing * 2));
6178 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6179 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6180 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6181 TmpInst.addOperand(Inst.getOperand(4));
6182 Inst = TmpInst;
6183 return true;
6184 }
6185
6186 case ARM::VLD3DUPdWB_fixed_Asm_8:
6187 case ARM::VLD3DUPdWB_fixed_Asm_16:
6188 case ARM::VLD3DUPdWB_fixed_Asm_32:
6189 case ARM::VLD3DUPqWB_fixed_Asm_8:
6190 case ARM::VLD3DUPqWB_fixed_Asm_16:
6191 case ARM::VLD3DUPqWB_fixed_Asm_32: {
6192 MCInst TmpInst;
6193 unsigned Spacing;
6194 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6195 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6196 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6197 Spacing));
6198 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6199 Spacing * 2));
6200 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6201 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6202 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6203 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6204 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6205 TmpInst.addOperand(Inst.getOperand(4));
6206 Inst = TmpInst;
6207 return true;
6208 }
6209
6210 case ARM::VLD3DUPdWB_register_Asm_8:
6211 case ARM::VLD3DUPdWB_register_Asm_16:
6212 case ARM::VLD3DUPdWB_register_Asm_32:
6213 case ARM::VLD3DUPqWB_register_Asm_8:
6214 case ARM::VLD3DUPqWB_register_Asm_16:
6215 case ARM::VLD3DUPqWB_register_Asm_32: {
6216 MCInst TmpInst;
6217 unsigned Spacing;
6218 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6219 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6220 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6221 Spacing));
6222 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6223 Spacing * 2));
6224 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6225 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6226 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6227 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6228 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6229 TmpInst.addOperand(Inst.getOperand(5));
6230 Inst = TmpInst;
6231 return true;
6232 }
6233
Jim Grosbachc387fc62012-01-23 23:20:46 +00006234 // VLD3 multiple 3-element structure instructions.
6235 case ARM::VLD3dAsm_8:
6236 case ARM::VLD3dAsm_16:
6237 case ARM::VLD3dAsm_32:
6238 case ARM::VLD3qAsm_8:
6239 case ARM::VLD3qAsm_16:
6240 case ARM::VLD3qAsm_32: {
6241 MCInst TmpInst;
6242 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006243 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00006244 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6245 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6246 Spacing));
6247 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6248 Spacing * 2));
6249 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6250 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6251 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6252 TmpInst.addOperand(Inst.getOperand(4));
6253 Inst = TmpInst;
6254 return true;
6255 }
6256
6257 case ARM::VLD3dWB_fixed_Asm_8:
6258 case ARM::VLD3dWB_fixed_Asm_16:
6259 case ARM::VLD3dWB_fixed_Asm_32:
6260 case ARM::VLD3qWB_fixed_Asm_8:
6261 case ARM::VLD3qWB_fixed_Asm_16:
6262 case ARM::VLD3qWB_fixed_Asm_32: {
6263 MCInst TmpInst;
6264 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006265 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00006266 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6267 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6268 Spacing));
6269 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6270 Spacing * 2));
6271 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6272 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6273 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6274 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6275 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6276 TmpInst.addOperand(Inst.getOperand(4));
6277 Inst = TmpInst;
6278 return true;
6279 }
6280
6281 case ARM::VLD3dWB_register_Asm_8:
6282 case ARM::VLD3dWB_register_Asm_16:
6283 case ARM::VLD3dWB_register_Asm_32:
6284 case ARM::VLD3qWB_register_Asm_8:
6285 case ARM::VLD3qWB_register_Asm_16:
6286 case ARM::VLD3qWB_register_Asm_32: {
6287 MCInst TmpInst;
6288 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006289 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00006290 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6291 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6292 Spacing));
6293 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6294 Spacing * 2));
6295 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6296 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6297 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6298 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6299 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6300 TmpInst.addOperand(Inst.getOperand(5));
6301 Inst = TmpInst;
6302 return true;
6303 }
6304
Jim Grosbacha57a36a2012-01-25 00:01:08 +00006305 // VLD4DUP single 3-element structure to all lanes instructions.
6306 case ARM::VLD4DUPdAsm_8:
6307 case ARM::VLD4DUPdAsm_16:
6308 case ARM::VLD4DUPdAsm_32:
6309 case ARM::VLD4DUPqAsm_8:
6310 case ARM::VLD4DUPqAsm_16:
6311 case ARM::VLD4DUPqAsm_32: {
6312 MCInst TmpInst;
6313 unsigned Spacing;
6314 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6315 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6316 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6317 Spacing));
6318 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6319 Spacing * 2));
6320 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6321 Spacing * 3));
6322 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6323 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6324 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6325 TmpInst.addOperand(Inst.getOperand(4));
6326 Inst = TmpInst;
6327 return true;
6328 }
6329
6330 case ARM::VLD4DUPdWB_fixed_Asm_8:
6331 case ARM::VLD4DUPdWB_fixed_Asm_16:
6332 case ARM::VLD4DUPdWB_fixed_Asm_32:
6333 case ARM::VLD4DUPqWB_fixed_Asm_8:
6334 case ARM::VLD4DUPqWB_fixed_Asm_16:
6335 case ARM::VLD4DUPqWB_fixed_Asm_32: {
6336 MCInst TmpInst;
6337 unsigned Spacing;
6338 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6339 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6340 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6341 Spacing));
6342 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6343 Spacing * 2));
6344 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6345 Spacing * 3));
6346 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6347 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6348 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6349 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6350 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6351 TmpInst.addOperand(Inst.getOperand(4));
6352 Inst = TmpInst;
6353 return true;
6354 }
6355
6356 case ARM::VLD4DUPdWB_register_Asm_8:
6357 case ARM::VLD4DUPdWB_register_Asm_16:
6358 case ARM::VLD4DUPdWB_register_Asm_32:
6359 case ARM::VLD4DUPqWB_register_Asm_8:
6360 case ARM::VLD4DUPqWB_register_Asm_16:
6361 case ARM::VLD4DUPqWB_register_Asm_32: {
6362 MCInst TmpInst;
6363 unsigned Spacing;
6364 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6365 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6366 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6367 Spacing));
6368 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6369 Spacing * 2));
6370 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6371 Spacing * 3));
6372 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6373 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6374 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6375 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6376 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6377 TmpInst.addOperand(Inst.getOperand(5));
6378 Inst = TmpInst;
6379 return true;
6380 }
6381
6382 // VLD4 multiple 4-element structure instructions.
Jim Grosbach8abe7e32012-01-24 00:43:17 +00006383 case ARM::VLD4dAsm_8:
6384 case ARM::VLD4dAsm_16:
6385 case ARM::VLD4dAsm_32:
6386 case ARM::VLD4qAsm_8:
6387 case ARM::VLD4qAsm_16:
6388 case ARM::VLD4qAsm_32: {
6389 MCInst TmpInst;
6390 unsigned Spacing;
6391 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6392 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6393 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6394 Spacing));
6395 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6396 Spacing * 2));
6397 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6398 Spacing * 3));
6399 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6400 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6401 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6402 TmpInst.addOperand(Inst.getOperand(4));
6403 Inst = TmpInst;
6404 return true;
6405 }
6406
6407 case ARM::VLD4dWB_fixed_Asm_8:
6408 case ARM::VLD4dWB_fixed_Asm_16:
6409 case ARM::VLD4dWB_fixed_Asm_32:
6410 case ARM::VLD4qWB_fixed_Asm_8:
6411 case ARM::VLD4qWB_fixed_Asm_16:
6412 case ARM::VLD4qWB_fixed_Asm_32: {
6413 MCInst TmpInst;
6414 unsigned Spacing;
6415 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6416 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6417 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6418 Spacing));
6419 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6420 Spacing * 2));
6421 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6422 Spacing * 3));
6423 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6424 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6425 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6426 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6427 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6428 TmpInst.addOperand(Inst.getOperand(4));
6429 Inst = TmpInst;
6430 return true;
6431 }
6432
6433 case ARM::VLD4dWB_register_Asm_8:
6434 case ARM::VLD4dWB_register_Asm_16:
6435 case ARM::VLD4dWB_register_Asm_32:
6436 case ARM::VLD4qWB_register_Asm_8:
6437 case ARM::VLD4qWB_register_Asm_16:
6438 case ARM::VLD4qWB_register_Asm_32: {
6439 MCInst TmpInst;
6440 unsigned Spacing;
6441 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6442 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6443 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6444 Spacing));
6445 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6446 Spacing * 2));
6447 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6448 Spacing * 3));
6449 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6450 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6451 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6452 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6453 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6454 TmpInst.addOperand(Inst.getOperand(5));
6455 Inst = TmpInst;
6456 return true;
6457 }
6458
Jim Grosbachd7433e22012-01-23 23:45:44 +00006459 // VST3 multiple 3-element structure instructions.
6460 case ARM::VST3dAsm_8:
6461 case ARM::VST3dAsm_16:
6462 case ARM::VST3dAsm_32:
6463 case ARM::VST3qAsm_8:
6464 case ARM::VST3qAsm_16:
6465 case ARM::VST3qAsm_32: {
6466 MCInst TmpInst;
6467 unsigned Spacing;
6468 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6469 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6470 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6471 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6472 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6473 Spacing));
6474 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6475 Spacing * 2));
6476 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6477 TmpInst.addOperand(Inst.getOperand(4));
6478 Inst = TmpInst;
6479 return true;
6480 }
6481
6482 case ARM::VST3dWB_fixed_Asm_8:
6483 case ARM::VST3dWB_fixed_Asm_16:
6484 case ARM::VST3dWB_fixed_Asm_32:
6485 case ARM::VST3qWB_fixed_Asm_8:
6486 case ARM::VST3qWB_fixed_Asm_16:
6487 case ARM::VST3qWB_fixed_Asm_32: {
6488 MCInst TmpInst;
6489 unsigned Spacing;
6490 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6491 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6492 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6493 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6494 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6495 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6496 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6497 Spacing));
6498 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6499 Spacing * 2));
6500 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6501 TmpInst.addOperand(Inst.getOperand(4));
6502 Inst = TmpInst;
6503 return true;
6504 }
6505
6506 case ARM::VST3dWB_register_Asm_8:
6507 case ARM::VST3dWB_register_Asm_16:
6508 case ARM::VST3dWB_register_Asm_32:
6509 case ARM::VST3qWB_register_Asm_8:
6510 case ARM::VST3qWB_register_Asm_16:
6511 case ARM::VST3qWB_register_Asm_32: {
6512 MCInst TmpInst;
6513 unsigned Spacing;
6514 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6515 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6516 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6517 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6518 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6519 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6520 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6521 Spacing));
6522 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6523 Spacing * 2));
6524 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6525 TmpInst.addOperand(Inst.getOperand(5));
6526 Inst = TmpInst;
6527 return true;
6528 }
6529
Jim Grosbach539aab72012-01-24 00:58:13 +00006530 // VST4 multiple 3-element structure instructions.
6531 case ARM::VST4dAsm_8:
6532 case ARM::VST4dAsm_16:
6533 case ARM::VST4dAsm_32:
6534 case ARM::VST4qAsm_8:
6535 case ARM::VST4qAsm_16:
6536 case ARM::VST4qAsm_32: {
6537 MCInst TmpInst;
6538 unsigned Spacing;
6539 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6540 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6541 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6542 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6543 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6544 Spacing));
6545 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6546 Spacing * 2));
6547 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6548 Spacing * 3));
6549 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6550 TmpInst.addOperand(Inst.getOperand(4));
6551 Inst = TmpInst;
6552 return true;
6553 }
6554
6555 case ARM::VST4dWB_fixed_Asm_8:
6556 case ARM::VST4dWB_fixed_Asm_16:
6557 case ARM::VST4dWB_fixed_Asm_32:
6558 case ARM::VST4qWB_fixed_Asm_8:
6559 case ARM::VST4qWB_fixed_Asm_16:
6560 case ARM::VST4qWB_fixed_Asm_32: {
6561 MCInst TmpInst;
6562 unsigned Spacing;
6563 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6564 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6565 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6566 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6567 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6568 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6569 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6570 Spacing));
6571 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6572 Spacing * 2));
6573 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6574 Spacing * 3));
6575 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6576 TmpInst.addOperand(Inst.getOperand(4));
6577 Inst = TmpInst;
6578 return true;
6579 }
6580
6581 case ARM::VST4dWB_register_Asm_8:
6582 case ARM::VST4dWB_register_Asm_16:
6583 case ARM::VST4dWB_register_Asm_32:
6584 case ARM::VST4qWB_register_Asm_8:
6585 case ARM::VST4qWB_register_Asm_16:
6586 case ARM::VST4qWB_register_Asm_32: {
6587 MCInst TmpInst;
6588 unsigned Spacing;
6589 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6590 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6591 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6592 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6593 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6594 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6595 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6596 Spacing));
6597 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6598 Spacing * 2));
6599 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6600 Spacing * 3));
6601 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6602 TmpInst.addOperand(Inst.getOperand(5));
6603 Inst = TmpInst;
6604 return true;
6605 }
6606
Jim Grosbach863d2af2011-12-13 22:45:11 +00006607 // Handle the Thumb2 mode MOV complex aliases.
Jim Grosbach2cc5cda2011-12-21 20:54:00 +00006608 case ARM::t2MOVsr:
6609 case ARM::t2MOVSsr: {
6610 // Which instruction to expand to depends on the CCOut operand and
6611 // whether we're in an IT block if the register operands are low
6612 // registers.
6613 bool isNarrow = false;
6614 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6615 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6616 isARMLowRegister(Inst.getOperand(2).getReg()) &&
6617 Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
6618 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsr))
6619 isNarrow = true;
6620 MCInst TmpInst;
6621 unsigned newOpc;
6622 switch(ARM_AM::getSORegShOp(Inst.getOperand(3).getImm())) {
6623 default: llvm_unreachable("unexpected opcode!");
6624 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRrr : ARM::t2ASRrr; break;
6625 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRrr : ARM::t2LSRrr; break;
6626 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLrr : ARM::t2LSLrr; break;
6627 case ARM_AM::ror: newOpc = isNarrow ? ARM::tROR : ARM::t2RORrr; break;
6628 }
6629 TmpInst.setOpcode(newOpc);
6630 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6631 if (isNarrow)
6632 TmpInst.addOperand(MCOperand::CreateReg(
6633 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6634 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6635 TmpInst.addOperand(Inst.getOperand(2)); // Rm
6636 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6637 TmpInst.addOperand(Inst.getOperand(5));
6638 if (!isNarrow)
6639 TmpInst.addOperand(MCOperand::CreateReg(
6640 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6641 Inst = TmpInst;
6642 return true;
6643 }
Jim Grosbach863d2af2011-12-13 22:45:11 +00006644 case ARM::t2MOVsi:
6645 case ARM::t2MOVSsi: {
6646 // Which instruction to expand to depends on the CCOut operand and
6647 // whether we're in an IT block if the register operands are low
6648 // registers.
6649 bool isNarrow = false;
6650 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6651 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6652 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
6653 isNarrow = true;
6654 MCInst TmpInst;
6655 unsigned newOpc;
6656 switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
6657 default: llvm_unreachable("unexpected opcode!");
6658 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
6659 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
6660 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
6661 case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
Jim Grosbach520dc782011-12-21 21:04:19 +00006662 case ARM_AM::rrx: isNarrow = false; newOpc = ARM::t2RRX; break;
Jim Grosbach863d2af2011-12-13 22:45:11 +00006663 }
6664 unsigned Ammount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
6665 if (Ammount == 32) Ammount = 0;
6666 TmpInst.setOpcode(newOpc);
6667 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6668 if (isNarrow)
6669 TmpInst.addOperand(MCOperand::CreateReg(
6670 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6671 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbach520dc782011-12-21 21:04:19 +00006672 if (newOpc != ARM::t2RRX)
6673 TmpInst.addOperand(MCOperand::CreateImm(Ammount));
Jim Grosbach863d2af2011-12-13 22:45:11 +00006674 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6675 TmpInst.addOperand(Inst.getOperand(4));
6676 if (!isNarrow)
6677 TmpInst.addOperand(MCOperand::CreateReg(
6678 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6679 Inst = TmpInst;
6680 return true;
6681 }
6682 // Handle the ARM mode MOV complex aliases.
Jim Grosbach23f22072011-11-16 18:31:45 +00006683 case ARM::ASRr:
6684 case ARM::LSRr:
6685 case ARM::LSLr:
6686 case ARM::RORr: {
6687 ARM_AM::ShiftOpc ShiftTy;
6688 switch(Inst.getOpcode()) {
6689 default: llvm_unreachable("unexpected opcode!");
6690 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
6691 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
6692 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
6693 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
6694 }
Jim Grosbach23f22072011-11-16 18:31:45 +00006695 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
6696 MCInst TmpInst;
6697 TmpInst.setOpcode(ARM::MOVsr);
6698 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6699 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6700 TmpInst.addOperand(Inst.getOperand(2)); // Rm
6701 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6702 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6703 TmpInst.addOperand(Inst.getOperand(4));
6704 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6705 Inst = TmpInst;
6706 return true;
6707 }
Jim Grosbachee10ff82011-11-10 19:18:01 +00006708 case ARM::ASRi:
6709 case ARM::LSRi:
6710 case ARM::LSLi:
6711 case ARM::RORi: {
6712 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachee10ff82011-11-10 19:18:01 +00006713 switch(Inst.getOpcode()) {
6714 default: llvm_unreachable("unexpected opcode!");
6715 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
6716 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
6717 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
6718 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
6719 }
6720 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach48b368b2011-11-16 19:05:59 +00006721 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachee10ff82011-11-10 19:18:01 +00006722 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
6723 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach71810ab2011-11-10 16:44:55 +00006724 MCInst TmpInst;
Jim Grosbachee10ff82011-11-10 19:18:01 +00006725 TmpInst.setOpcode(Opc);
Jim Grosbach71810ab2011-11-10 16:44:55 +00006726 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6727 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachee10ff82011-11-10 19:18:01 +00006728 if (Opc == ARM::MOVsi)
6729 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach71810ab2011-11-10 16:44:55 +00006730 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6731 TmpInst.addOperand(Inst.getOperand(4));
6732 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6733 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006734 return true;
Jim Grosbach71810ab2011-11-10 16:44:55 +00006735 }
Jim Grosbach48b368b2011-11-16 19:05:59 +00006736 case ARM::RRXi: {
6737 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
6738 MCInst TmpInst;
6739 TmpInst.setOpcode(ARM::MOVsi);
6740 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6741 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6742 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6743 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6744 TmpInst.addOperand(Inst.getOperand(3));
6745 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
6746 Inst = TmpInst;
6747 return true;
6748 }
Jim Grosbach0352b462011-11-10 23:58:34 +00006749 case ARM::t2LDMIA_UPD: {
6750 // If this is a load of a single register, then we should use
6751 // a post-indexed LDR instruction instead, per the ARM ARM.
6752 if (Inst.getNumOperands() != 5)
6753 return false;
6754 MCInst TmpInst;
6755 TmpInst.setOpcode(ARM::t2LDR_POST);
6756 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6757 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6758 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6759 TmpInst.addOperand(MCOperand::CreateImm(4));
6760 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6761 TmpInst.addOperand(Inst.getOperand(3));
6762 Inst = TmpInst;
6763 return true;
6764 }
6765 case ARM::t2STMDB_UPD: {
6766 // If this is a store of a single register, then we should use
6767 // a pre-indexed STR instruction instead, per the ARM ARM.
6768 if (Inst.getNumOperands() != 5)
6769 return false;
6770 MCInst TmpInst;
6771 TmpInst.setOpcode(ARM::t2STR_PRE);
6772 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6773 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6774 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6775 TmpInst.addOperand(MCOperand::CreateImm(-4));
6776 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6777 TmpInst.addOperand(Inst.getOperand(3));
6778 Inst = TmpInst;
6779 return true;
6780 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00006781 case ARM::LDMIA_UPD:
6782 // If this is a load of a single register via a 'pop', then we should use
6783 // a post-indexed LDR instruction instead, per the ARM ARM.
6784 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
6785 Inst.getNumOperands() == 5) {
6786 MCInst TmpInst;
6787 TmpInst.setOpcode(ARM::LDR_POST_IMM);
6788 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6789 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6790 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6791 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
6792 TmpInst.addOperand(MCOperand::CreateImm(4));
6793 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6794 TmpInst.addOperand(Inst.getOperand(3));
6795 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006796 return true;
Jim Grosbachf8fce712011-08-11 17:35:48 +00006797 }
6798 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00006799 case ARM::STMDB_UPD:
6800 // If this is a store of a single register via a 'push', then we should use
6801 // a pre-indexed STR instruction instead, per the ARM ARM.
6802 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
6803 Inst.getNumOperands() == 5) {
6804 MCInst TmpInst;
6805 TmpInst.setOpcode(ARM::STR_PRE_IMM);
6806 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6807 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6808 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
6809 TmpInst.addOperand(MCOperand::CreateImm(-4));
6810 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6811 TmpInst.addOperand(Inst.getOperand(3));
6812 Inst = TmpInst;
6813 }
6814 break;
Jim Grosbachda847862011-12-05 21:06:26 +00006815 case ARM::t2ADDri12:
6816 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
6817 // mnemonic was used (not "addw"), encoding T3 is preferred.
6818 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
6819 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
6820 break;
6821 Inst.setOpcode(ARM::t2ADDri);
6822 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
6823 break;
6824 case ARM::t2SUBri12:
6825 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
6826 // mnemonic was used (not "subw"), encoding T3 is preferred.
6827 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
6828 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
6829 break;
6830 Inst.setOpcode(ARM::t2SUBri);
6831 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
6832 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006833 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00006834 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6835 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6836 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6837 // to encoding T1 if <Rd> is omitted."
Jim Grosbachc0164f82012-03-30 16:31:31 +00006838 if ((unsigned)Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006839 Inst.setOpcode(ARM::tADDi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006840 return true;
6841 }
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006842 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00006843 case ARM::tSUBi8:
6844 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6845 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6846 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6847 // to encoding T1 if <Rd> is omitted."
Jim Grosbachc0164f82012-03-30 16:31:31 +00006848 if ((unsigned)Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachf67e8552011-09-16 22:58:42 +00006849 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006850 return true;
6851 }
Jim Grosbachf67e8552011-09-16 22:58:42 +00006852 break;
Jim Grosbach2d30d942012-03-30 17:20:40 +00006853 case ARM::t2ADDri:
6854 case ARM::t2SUBri: {
6855 // If the destination and first source operand are the same, and
6856 // the flags are compatible with the current IT status, use encoding T2
6857 // instead of T3. For compatibility with the system 'as'. Make sure the
6858 // wide encoding wasn't explicit.
6859 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
6860 (unsigned)Inst.getOperand(2).getImm() > 255 ||
6861 ((!inITBlock() && Inst.getOperand(5).getReg() != ARM::CPSR) ||
6862 (inITBlock() && Inst.getOperand(5).getReg() != 0)) ||
6863 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6864 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
6865 break;
6866 MCInst TmpInst;
6867 TmpInst.setOpcode(Inst.getOpcode() == ARM::t2ADDri ?
6868 ARM::tADDi8 : ARM::tSUBi8);
6869 TmpInst.addOperand(Inst.getOperand(0));
6870 TmpInst.addOperand(Inst.getOperand(5));
6871 TmpInst.addOperand(Inst.getOperand(0));
6872 TmpInst.addOperand(Inst.getOperand(2));
6873 TmpInst.addOperand(Inst.getOperand(3));
6874 TmpInst.addOperand(Inst.getOperand(4));
6875 Inst = TmpInst;
6876 return true;
6877 }
Jim Grosbach927b9df2011-12-05 22:16:39 +00006878 case ARM::t2ADDrr: {
6879 // If the destination and first source operand are the same, and
6880 // there's no setting of the flags, use encoding T2 instead of T3.
6881 // Note that this is only for ADD, not SUB. This mirrors the system
6882 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
6883 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
6884 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbach713c7022011-12-05 22:27:04 +00006885 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6886 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbach927b9df2011-12-05 22:16:39 +00006887 break;
6888 MCInst TmpInst;
6889 TmpInst.setOpcode(ARM::tADDhirr);
6890 TmpInst.addOperand(Inst.getOperand(0));
6891 TmpInst.addOperand(Inst.getOperand(0));
6892 TmpInst.addOperand(Inst.getOperand(2));
6893 TmpInst.addOperand(Inst.getOperand(3));
6894 TmpInst.addOperand(Inst.getOperand(4));
6895 Inst = TmpInst;
6896 return true;
6897 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006898 case ARM::tB:
6899 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006900 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006901 Inst.setOpcode(ARM::tBcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006902 return true;
6903 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006904 break;
6905 case ARM::t2B:
6906 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006907 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006908 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006909 return true;
6910 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006911 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00006912 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00006913 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006914 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbachc0755102011-08-31 21:17:31 +00006915 Inst.setOpcode(ARM::t2B);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006916 return true;
6917 }
Jim Grosbachc0755102011-08-31 21:17:31 +00006918 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00006919 case ARM::tBcc:
6920 // If the conditional is AL, we really want tB.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006921 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbach395b4532011-08-17 22:57:40 +00006922 Inst.setOpcode(ARM::tB);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006923 return true;
6924 }
Jim Grosbach3ce23d32011-08-18 16:08:39 +00006925 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00006926 case ARM::tLDMIA: {
6927 // If the register list contains any high registers, or if the writeback
6928 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
6929 // instead if we're in Thumb2. Otherwise, this should have generated
6930 // an error in validateInstruction().
6931 unsigned Rn = Inst.getOperand(0).getReg();
6932 bool hasWritebackToken =
6933 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6934 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
6935 bool listContainsBase;
6936 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
6937 (!listContainsBase && !hasWritebackToken) ||
6938 (listContainsBase && hasWritebackToken)) {
6939 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6940 assert (isThumbTwo());
6941 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
6942 // If we're switching to the updating version, we need to insert
6943 // the writeback tied operand.
6944 if (hasWritebackToken)
6945 Inst.insert(Inst.begin(),
6946 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006947 return true;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00006948 }
6949 break;
6950 }
Jim Grosbach8213c962011-09-16 20:50:13 +00006951 case ARM::tSTMIA_UPD: {
6952 // If the register list contains any high registers, we need to use
6953 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6954 // should have generated an error in validateInstruction().
6955 unsigned Rn = Inst.getOperand(0).getReg();
6956 bool listContainsBase;
6957 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
6958 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6959 assert (isThumbTwo());
6960 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006961 return true;
Jim Grosbach8213c962011-09-16 20:50:13 +00006962 }
6963 break;
6964 }
Jim Grosbach54026372011-11-10 23:17:11 +00006965 case ARM::tPOP: {
6966 bool listContainsBase;
6967 // If the register list contains any high registers, we need to use
6968 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6969 // should have generated an error in validateInstruction().
6970 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00006971 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00006972 assert (isThumbTwo());
6973 Inst.setOpcode(ARM::t2LDMIA_UPD);
6974 // Add the base register and writeback operands.
6975 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6976 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006977 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00006978 }
6979 case ARM::tPUSH: {
6980 bool listContainsBase;
6981 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00006982 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00006983 assert (isThumbTwo());
6984 Inst.setOpcode(ARM::t2STMDB_UPD);
6985 // Add the base register and writeback operands.
6986 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6987 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006988 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00006989 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006990 case ARM::t2MOVi: {
6991 // If we can use the 16-bit encoding and the user didn't explicitly
6992 // request the 32-bit variant, transform it here.
6993 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
Jim Grosbachc0164f82012-03-30 16:31:31 +00006994 (unsigned)Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00006995 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
6996 Inst.getOperand(4).getReg() == ARM::CPSR) ||
6997 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006998 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6999 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
7000 // The operands aren't in the same order for tMOVi8...
7001 MCInst TmpInst;
7002 TmpInst.setOpcode(ARM::tMOVi8);
7003 TmpInst.addOperand(Inst.getOperand(0));
7004 TmpInst.addOperand(Inst.getOperand(4));
7005 TmpInst.addOperand(Inst.getOperand(1));
7006 TmpInst.addOperand(Inst.getOperand(2));
7007 TmpInst.addOperand(Inst.getOperand(3));
7008 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00007009 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00007010 }
7011 break;
7012 }
7013 case ARM::t2MOVr: {
7014 // If we can use the 16-bit encoding and the user didn't explicitly
7015 // request the 32-bit variant, transform it here.
7016 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
7017 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7018 Inst.getOperand(2).getImm() == ARMCC::AL &&
7019 Inst.getOperand(4).getReg() == ARM::CPSR &&
7020 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
7021 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
7022 // The operands aren't the same for tMOV[S]r... (no cc_out)
7023 MCInst TmpInst;
7024 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
7025 TmpInst.addOperand(Inst.getOperand(0));
7026 TmpInst.addOperand(Inst.getOperand(1));
7027 TmpInst.addOperand(Inst.getOperand(2));
7028 TmpInst.addOperand(Inst.getOperand(3));
7029 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00007030 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00007031 }
7032 break;
7033 }
Jim Grosbach326efe52011-09-19 20:29:33 +00007034 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00007035 case ARM::t2SXTB:
7036 case ARM::t2UXTH:
7037 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00007038 // If we can use the 16-bit encoding and the user didn't explicitly
7039 // request the 32-bit variant, transform it here.
7040 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
7041 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7042 Inst.getOperand(2).getImm() == 0 &&
7043 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
7044 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00007045 unsigned NewOpc;
7046 switch (Inst.getOpcode()) {
7047 default: llvm_unreachable("Illegal opcode!");
7048 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
7049 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
7050 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
7051 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
7052 }
Jim Grosbach326efe52011-09-19 20:29:33 +00007053 // The operands aren't the same for thumb1 (no rotate operand).
7054 MCInst TmpInst;
7055 TmpInst.setOpcode(NewOpc);
7056 TmpInst.addOperand(Inst.getOperand(0));
7057 TmpInst.addOperand(Inst.getOperand(1));
7058 TmpInst.addOperand(Inst.getOperand(3));
7059 TmpInst.addOperand(Inst.getOperand(4));
7060 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00007061 return true;
Jim Grosbach326efe52011-09-19 20:29:33 +00007062 }
7063 break;
7064 }
Jim Grosbach04b5d932011-12-20 00:59:38 +00007065 case ARM::MOVsi: {
7066 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm());
7067 if (SOpc == ARM_AM::rrx) return false;
7068 if (ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()) == 0) {
7069 // Shifting by zero is accepted as a vanilla 'MOVr'
7070 MCInst TmpInst;
7071 TmpInst.setOpcode(ARM::MOVr);
7072 TmpInst.addOperand(Inst.getOperand(0));
7073 TmpInst.addOperand(Inst.getOperand(1));
7074 TmpInst.addOperand(Inst.getOperand(3));
7075 TmpInst.addOperand(Inst.getOperand(4));
7076 TmpInst.addOperand(Inst.getOperand(5));
7077 Inst = TmpInst;
7078 return true;
7079 }
7080 return false;
7081 }
Jim Grosbach8d9550b2011-12-22 18:04:04 +00007082 case ARM::ANDrsi:
7083 case ARM::ORRrsi:
7084 case ARM::EORrsi:
7085 case ARM::BICrsi:
7086 case ARM::SUBrsi:
7087 case ARM::ADDrsi: {
7088 unsigned newOpc;
7089 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(3).getImm());
7090 if (SOpc == ARM_AM::rrx) return false;
7091 switch (Inst.getOpcode()) {
Craig Topperbc219812012-02-07 02:50:20 +00007092 default: llvm_unreachable("unexpected opcode!");
Jim Grosbach8d9550b2011-12-22 18:04:04 +00007093 case ARM::ANDrsi: newOpc = ARM::ANDrr; break;
7094 case ARM::ORRrsi: newOpc = ARM::ORRrr; break;
7095 case ARM::EORrsi: newOpc = ARM::EORrr; break;
7096 case ARM::BICrsi: newOpc = ARM::BICrr; break;
7097 case ARM::SUBrsi: newOpc = ARM::SUBrr; break;
7098 case ARM::ADDrsi: newOpc = ARM::ADDrr; break;
7099 }
7100 // If the shift is by zero, use the non-shifted instruction definition.
7101 if (ARM_AM::getSORegOffset(Inst.getOperand(3).getImm()) == 0) {
7102 MCInst TmpInst;
7103 TmpInst.setOpcode(newOpc);
7104 TmpInst.addOperand(Inst.getOperand(0));
7105 TmpInst.addOperand(Inst.getOperand(1));
7106 TmpInst.addOperand(Inst.getOperand(2));
7107 TmpInst.addOperand(Inst.getOperand(4));
7108 TmpInst.addOperand(Inst.getOperand(5));
7109 TmpInst.addOperand(Inst.getOperand(6));
7110 Inst = TmpInst;
7111 return true;
7112 }
7113 return false;
7114 }
Jim Grosbach74423e32012-01-25 19:52:01 +00007115 case ARM::ITasm:
Jim Grosbach89df9962011-08-26 21:43:41 +00007116 case ARM::t2IT: {
7117 // The mask bits for all but the first condition are represented as
7118 // the low bit of the condition code value implies 't'. We currently
7119 // always have 1 implies 't', so XOR toggle the bits if the low bit
7120 // of the condition code is zero. The encoding also expects the low
7121 // bit of the condition to be encoded as bit 4 of the mask operand,
7122 // so mask that in if needed
7123 MCOperand &MO = Inst.getOperand(1);
7124 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007125 unsigned OrigMask = Mask;
7126 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00007127 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00007128 assert(Mask && TZ <= 3 && "illegal IT mask value!");
7129 for (unsigned i = 3; i != TZ; --i)
7130 Mask ^= 1 << i;
7131 } else
7132 Mask |= 0x10;
7133 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007134
7135 // Set up the IT block state according to the IT instruction we just
7136 // matched.
7137 assert(!inITBlock() && "nested IT blocks?!");
7138 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
7139 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
7140 ITState.CurPosition = 0;
7141 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00007142 break;
7143 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00007144 }
Jim Grosbach83ec8772011-11-10 23:42:14 +00007145 return false;
Jim Grosbachf8fce712011-08-11 17:35:48 +00007146}
7147
Jim Grosbach47a0d522011-08-16 20:45:50 +00007148unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
7149 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
7150 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00007151 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00007152 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00007153 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
7154 assert(MCID.hasOptionalDef() &&
7155 "optionally flag setting instruction missing optional def operand");
7156 assert(MCID.NumOperands == Inst.getNumOperands() &&
7157 "operand count mismatch!");
7158 // Find the optional-def operand (cc_out).
7159 unsigned OpNo;
7160 for (OpNo = 0;
7161 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
7162 ++OpNo)
7163 ;
7164 // If we're parsing Thumb1, reject it completely.
7165 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
7166 return Match_MnemonicFail;
7167 // If we're parsing Thumb2, which form is legal depends on whether we're
7168 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007169 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
7170 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00007171 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007172 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
7173 inITBlock())
7174 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00007175 }
Jim Grosbach194bd892011-08-16 22:20:01 +00007176 // Some high-register supporting Thumb1 encodings only allow both registers
7177 // to be from r0-r7 when in Thumb2.
7178 else if (Opc == ARM::tADDhirr && isThumbOne() &&
7179 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7180 isARMLowRegister(Inst.getOperand(2).getReg()))
7181 return Match_RequiresThumb2;
7182 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00007183 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00007184 isARMLowRegister(Inst.getOperand(0).getReg()) &&
7185 isARMLowRegister(Inst.getOperand(1).getReg()))
7186 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00007187 return Match_Success;
7188}
7189
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007190bool ARMAsmParser::
7191MatchAndEmitInstruction(SMLoc IDLoc,
7192 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
7193 MCStreamer &Out) {
7194 MCInst Inst;
7195 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00007196 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00007197 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00007198 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00007199 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00007200 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00007201 // Context sensitive operand constraints aren't handled by the matcher,
7202 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00007203 if (validateInstruction(Inst, Operands)) {
7204 // Still progress the IT block, otherwise one wrong condition causes
7205 // nasty cascading errors.
7206 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00007207 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00007208 }
Jim Grosbach189610f2011-07-26 18:25:39 +00007209
Jim Grosbachf8fce712011-08-11 17:35:48 +00007210 // Some instructions need post-processing to, for example, tweak which
Jim Grosbach83ec8772011-11-10 23:42:14 +00007211 // encoding is selected. Loop on it while changes happen so the
7212 // individual transformations can chain off each other. E.g.,
7213 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
7214 while (processInstruction(Inst, Operands))
7215 ;
Jim Grosbachf8fce712011-08-11 17:35:48 +00007216
Jim Grosbacha1109882011-09-02 23:22:08 +00007217 // Only move forward at the very end so that everything in validate
7218 // and process gets a consistent answer about whether we're in an IT
7219 // block.
7220 forwardITPosition();
7221
Jim Grosbach74423e32012-01-25 19:52:01 +00007222 // ITasm is an ARM mode pseudo-instruction that just sets the ITblock and
7223 // doesn't actually encode.
7224 if (Inst.getOpcode() == ARM::ITasm)
7225 return false;
7226
Jim Grosbach42e6bd32012-01-26 23:20:15 +00007227 Inst.setLoc(IDLoc);
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007228 Out.EmitInstruction(Inst);
7229 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00007230 case Match_MissingFeature:
7231 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
7232 return true;
7233 case Match_InvalidOperand: {
7234 SMLoc ErrorLoc = IDLoc;
7235 if (ErrorInfo != ~0U) {
7236 if (ErrorInfo >= Operands.size())
7237 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00007238
Chris Lattnere73d4f82010-10-28 21:41:58 +00007239 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
7240 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
7241 }
Jim Grosbach16c74252010-10-29 14:46:02 +00007242
Chris Lattnere73d4f82010-10-28 21:41:58 +00007243 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007244 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00007245 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00007246 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00007247 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00007248 // The converter function will have already emited a diagnostic.
7249 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007250 case Match_RequiresNotITBlock:
7251 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00007252 case Match_RequiresITBlock:
7253 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00007254 case Match_RequiresV6:
7255 return Error(IDLoc, "instruction variant requires ARMv6 or later");
7256 case Match_RequiresThumb2:
7257 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00007258 }
Jim Grosbach16c74252010-10-29 14:46:02 +00007259
Eric Christopherc223e2b2010-10-29 09:26:59 +00007260 llvm_unreachable("Implement any new match types added!");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007261}
7262
Jim Grosbach1355cf12011-07-26 17:10:22 +00007263/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007264bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
7265 StringRef IDVal = DirectiveID.getIdentifier();
7266 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007267 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007268 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007269 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach9a70df92011-12-07 18:04:19 +00007270 else if (IDVal == ".arm")
7271 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007272 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007273 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007274 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007275 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007276 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007277 return parseDirectiveSyntax(DirectiveID.getLoc());
Jim Grosbacha39cda72011-12-14 02:16:11 +00007278 else if (IDVal == ".unreq")
7279 return parseDirectiveUnreq(DirectiveID.getLoc());
Jason W Kimd7c9e082011-12-20 17:38:12 +00007280 else if (IDVal == ".arch")
7281 return parseDirectiveArch(DirectiveID.getLoc());
7282 else if (IDVal == ".eabi_attribute")
7283 return parseDirectiveEabiAttr(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007284 return true;
7285}
7286
Jim Grosbach1355cf12011-07-26 17:10:22 +00007287/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007288/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00007289bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007290 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7291 for (;;) {
7292 const MCExpr *Value;
7293 if (getParser().ParseExpression(Value))
7294 return true;
7295
Chris Lattneraaec2052010-01-19 19:46:13 +00007296 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007297
7298 if (getLexer().is(AsmToken::EndOfStatement))
7299 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00007300
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007301 // FIXME: Improve diagnostic.
7302 if (getLexer().isNot(AsmToken::Comma))
7303 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007304 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007305 }
7306 }
7307
Sean Callananb9a25b72010-01-19 20:27:46 +00007308 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007309 return false;
7310}
7311
Jim Grosbach1355cf12011-07-26 17:10:22 +00007312/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00007313/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00007314bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00007315 if (getLexer().isNot(AsmToken::EndOfStatement))
7316 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007317 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007318
Jim Grosbach9a70df92011-12-07 18:04:19 +00007319 if (!isThumb())
7320 SwitchMode();
7321 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
7322 return false;
7323}
7324
7325/// parseDirectiveARM
7326/// ::= .arm
7327bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
7328 if (getLexer().isNot(AsmToken::EndOfStatement))
7329 return Error(L, "unexpected token in directive");
7330 Parser.Lex();
7331
7332 if (isThumb())
7333 SwitchMode();
7334 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby515d5092009-10-15 20:48:48 +00007335 return false;
7336}
7337
Jim Grosbach1355cf12011-07-26 17:10:22 +00007338/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00007339/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00007340bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00007341 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
7342 bool isMachO = MAI.hasSubsectionsViaSymbols();
7343 StringRef Name;
Jim Grosbachde4d8392011-12-21 22:30:16 +00007344 bool needFuncName = true;
Rafael Espindola64695402011-05-16 16:17:21 +00007345
Jim Grosbachde4d8392011-12-21 22:30:16 +00007346 // Darwin asm has (optionally) function name after .thumb_func direction
Rafael Espindola64695402011-05-16 16:17:21 +00007347 // ELF doesn't
7348 if (isMachO) {
7349 const AsmToken &Tok = Parser.getTok();
Jim Grosbachde4d8392011-12-21 22:30:16 +00007350 if (Tok.isNot(AsmToken::EndOfStatement)) {
7351 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
7352 return Error(L, "unexpected token in .thumb_func directive");
7353 Name = Tok.getIdentifier();
7354 Parser.Lex(); // Consume the identifier token.
7355 needFuncName = false;
7356 }
Rafael Espindola64695402011-05-16 16:17:21 +00007357 }
7358
Jim Grosbachde4d8392011-12-21 22:30:16 +00007359 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby515d5092009-10-15 20:48:48 +00007360 return Error(L, "unexpected token in directive");
Jim Grosbachde4d8392011-12-21 22:30:16 +00007361
7362 // Eat the end of statement and any blank lines that follow.
7363 while (getLexer().is(AsmToken::EndOfStatement))
7364 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007365
Rafael Espindola64695402011-05-16 16:17:21 +00007366 // FIXME: assuming function name will be the line following .thumb_func
Jim Grosbachde4d8392011-12-21 22:30:16 +00007367 // We really should be checking the next symbol definition even if there's
7368 // stuff in between.
7369 if (needFuncName) {
Jim Grosbachd475f862011-11-10 20:48:53 +00007370 Name = Parser.getTok().getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00007371 }
7372
Jim Grosbach642fc9c2010-11-05 22:33:53 +00007373 // Mark symbol as a thumb symbol.
7374 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
7375 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00007376 return false;
7377}
7378
Jim Grosbach1355cf12011-07-26 17:10:22 +00007379/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00007380/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00007381bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00007382 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00007383 if (Tok.isNot(AsmToken::Identifier))
7384 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00007385 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00007386 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00007387 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00007388 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00007389 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00007390 else
7391 return Error(L, "unrecognized syntax mode in .syntax directive");
7392
7393 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00007394 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007395 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007396
7397 // TODO tell the MC streamer the mode
7398 // getParser().getStreamer().Emit???();
7399 return false;
7400}
7401
Jim Grosbach1355cf12011-07-26 17:10:22 +00007402/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00007403/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00007404bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00007405 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00007406 if (Tok.isNot(AsmToken::Integer))
7407 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00007408 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00007409 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00007410 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00007411 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00007412 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007413 else
7414 return Error(L, "invalid operand to .code directive");
7415
7416 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00007417 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007418 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007419
Evan Cheng32869202011-07-08 22:36:29 +00007420 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00007421 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00007422 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00007423 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00007424 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00007425 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00007426 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00007427 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00007428 }
Jim Grosbach2a301702010-11-05 22:40:53 +00007429
Kevin Enderby515d5092009-10-15 20:48:48 +00007430 return false;
7431}
7432
Jim Grosbacha39cda72011-12-14 02:16:11 +00007433/// parseDirectiveReq
7434/// ::= name .req registername
7435bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
7436 Parser.Lex(); // Eat the '.req' token.
7437 unsigned Reg;
7438 SMLoc SRegLoc, ERegLoc;
7439 if (ParseRegister(Reg, SRegLoc, ERegLoc)) {
7440 Parser.EatToEndOfStatement();
7441 return Error(SRegLoc, "register name expected");
7442 }
7443
7444 // Shouldn't be anything else.
7445 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
7446 Parser.EatToEndOfStatement();
7447 return Error(Parser.getTok().getLoc(),
7448 "unexpected input in .req directive.");
7449 }
7450
7451 Parser.Lex(); // Consume the EndOfStatement
7452
7453 if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg)
7454 return Error(SRegLoc, "redefinition of '" + Name +
7455 "' does not match original.");
7456
7457 return false;
7458}
7459
7460/// parseDirectiveUneq
7461/// ::= .unreq registername
7462bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
7463 if (Parser.getTok().isNot(AsmToken::Identifier)) {
7464 Parser.EatToEndOfStatement();
7465 return Error(L, "unexpected input in .unreq directive.");
7466 }
7467 RegisterReqs.erase(Parser.getTok().getIdentifier());
7468 Parser.Lex(); // Eat the identifier.
7469 return false;
7470}
7471
Jason W Kimd7c9e082011-12-20 17:38:12 +00007472/// parseDirectiveArch
7473/// ::= .arch token
7474bool ARMAsmParser::parseDirectiveArch(SMLoc L) {
7475 return true;
7476}
7477
7478/// parseDirectiveEabiAttr
7479/// ::= .eabi_attribute int, int
7480bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
7481 return true;
7482}
7483
Sean Callanan90b70972010-04-07 20:29:34 +00007484extern "C" void LLVMInitializeARMAsmLexer();
7485
Kevin Enderby9c41fa82009-10-30 22:55:57 +00007486/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007487extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00007488 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
7489 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00007490 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007491}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00007492
Chris Lattner0692ee62010-09-06 19:11:01 +00007493#define GET_REGISTER_MATCHER
7494#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00007495#include "ARMGenAsmMatcher.inc"